一些基础组件

This commit is contained in:
2026-08-30 03:52:23 +08:00
parent f26534c938
commit 37fddc0bdd
11 changed files with 1595 additions and 73 deletions
+82 -47
View File
@@ -1,57 +1,92 @@
#include "c_SmartPtr.h"
#include <stdlib.h>
#include <stdio.h>
#include "c_Test.h"
// 自訂釋放函數:負責關閉檔案
void close_file_callback(void* ptr, void* args) {
FILE* fp = (FILE*)ptr;
char* filename = (char*)args;
typedef struct {
int conn_fd;
} NetSession_t;
if (fp) {
printf("[SmartPtr] 引用計數歸零,自動關閉檔案: %s\n", filename);
fclose(fp);
static int g_session_free_call_count = 0;
static size_t g_buddy_pool_active_chunks = 0; // 審計夥伴系統記憶體池的活躍塊總數
// 自定義析構回呼
static void session_release_handler(void* ptr, void* args) {
if (ptr) {
free(ptr); // 釋放業務物件
g_session_free_call_count++;
}
}
int main() {
printf("--- 1. 建立資源 (Open File) ---\n");
char* my_file = "test.txt";
FILE* fp = fopen(my_file, "w");
if (!fp) return 1;
// 寫入一些測試資料
fprintf(fp, "Hello Smart Pointer in C!");
fflush(fp); // 確保資料進硬碟,但先不關閉檔案
// 使用智慧指標接管檔案控制權
c_SmartPtr_t sptr_a = c_SmartPtr_Make(fp, close_file_callback, my_file);
printf("sptr_a 建立完成,目前引用計數: %d\n", c_SmartPtr_UseCount(&sptr_a));
// 建立另外兩個空白的智慧指標容器
c_SmartPtr_t sptr_b = {0};
c_SmartPtr_t sptr_c = {0};
printf("\n--- 2. 測試 Copy 語義 (共享檔案控制權) ---\n");
c_SmartPtr_Copy(&sptr_b, &sptr_a);
printf("A 的計數: %d, B 的計數: %d\n", c_SmartPtr_UseCount(&sptr_a), c_SmartPtr_UseCount(&sptr_b));
printf("\n--- 3. 測試 Move 語義 (B 所有權轉移給 C) ---\n");
c_SmartPtr_Move(&sptr_c, &sptr_b);
printf("Move 後 -> B 計數: %d (已空), C 計數: %d\n", c_SmartPtr_UseCount(&sptr_b), c_SmartPtr_UseCount(&sptr_c));
printf("\n--- 4. 開始依序銷毀指標物件 ---\n");
printf("銷毀 sptr_a...\n");
c_SmartPtr_Destroy(&sptr_a); // 計數 2 -> 1
printf("sptr_a 銷毀後,C 的計數: %d\n", c_SmartPtr_UseCount(&sptr_c));
printf("銷毀 sptr_b (本身已空,無影響)...\n");
c_SmartPtr_Destroy(&sptr_b);
printf("銷毀 sptr_c...\n");
// 計數 1 -> 0,自動觸發 close_file_callback 關閉檔案!
c_SmartPtr_Destroy(&sptr_c);
printf("\n程式結束,所有資源安全回收。\n");
return 0;
// 模擬夥伴系統多態分配器物理開闢
static void* mock_buddy_alloc(size_t size, void* ctx) {
(void)ctx; g_buddy_pool_active_chunks++; return malloc(size);
}
static void mock_buddy_free(void* ptr, void* ctx) {
(void)ctx; if (ptr) g_buddy_pool_active_chunks--; free(ptr);
}
TEST_CASE(test_fully_closed_smart_pointer_polymorphic_sandbox) {
g_session_free_call_count = 0;
g_buddy_pool_active_chunks = 0;
// 1. 初始化你的自建多態記憶體池分配器 (夥伴系統物理底座)
c_Allocator_t buddy_pool = {
.alloc = mock_buddy_alloc,
.realloc = NULL,
.free = mock_buddy_free,
.dtor = NULL,
.ud = NULL
};
// 2. 在堆上構建一個真實的連線工作階段
NetSession_t* raw_session = (NetSession_t*)malloc(sizeof(NetSession_t));
raw_session->conn_fd = 8080;
// 3. 宣告主智慧指標誕生,並掛載夥伴系統記憶體池
c_SmartPtr_t sptr_master = c_SmartPtr_Make(raw_session, session_release_handler, NULL, &buddy_pool);
// 斷言審判:此時夥伴系統內部的活躍物理塊計數精準等於 1 (即內嵌 allocator 幫我們開闢的 ref_count)
ASSERT_INT_EQ(1, g_buddy_pool_active_chunks);
ASSERT_INT_EQ(1, c_SmartPtr_UseCount(&sptr_master));
// 4. 驗證共享深度拷貝與分配器血脈克隆繼承 (Copy)
c_SmartPtr_t sptr_clone = {0};
ASSERT_INT_EQ(C_ERR_OK, c_SmartPtr_Copy(&sptr_clone, &sptr_master));
// 兩者共享原子核,計數精準遞增為 2
ASSERT_INT_EQ(2, c_SmartPtr_UseCount(&sptr_master));
ASSERT_INT_EQ(2, c_SmartPtr_UseCount(&sptr_clone));
// 5. 【終極高能觀察點】:單體自主銷毀(Destroy)
// 外部直接呼叫極簡的 c_SmartPtr_Destroy,不需要傳入任何外部分配器!
c_SmartPtr_Destroy(&sptr_clone); // 克隆體釋放,計數精準回落至 1
// 帳目審查:克隆體被銷毀,但主體還活著,實體對象絕不能提前消亡,且夥伴系統計數依然完整保持為 1
ASSERT_INT_EQ(1, c_SmartPtr_UseCount(&sptr_master));
ASSERT_INT_EQ(0, g_session_free_call_count);
ASSERT_INT_EQ(1, g_buddy_pool_active_chunks);
// 6. 終致命一擊:銷毀最後持有人 sptr_master
// 計數歸零,自主觸發託管的 session_release_handler 物理火化,並【自主】利用內嵌的 allocator 退還記憶體
c_SmartPtr_Destroy(&sptr_master);
// 7. 終極一致性雙向審判:
// A. 實體資源層:業務物件被精準自動火化解體,物理消亡數精準等於 1
ASSERT_INT_EQ(1, g_session_free_call_count);
// B. 多態記憶體池層:分散隨機開闢的原子計數核空間完全由智慧指標內部自主歸還!
// 夥伴系統記憶體池活躍塊計數 g_buddy_pool_active_chunks 完美且毫無滯留地歸零(0 洩漏,0 跑飛,100% 圓滿!)
ASSERT_INT_EQ_MSG(0, g_buddy_pool_active_chunks, "CRITICAL: Self-contained Smart Pointer leaked ref_count space inside buddy pool!");
}
int main(void) {
printf("\n");
TEST_START(C_Ultimate_FullyClosed_SmartPtr_Tests);
RUN_TEST(test_fully_closed_smart_pointer_polymorphic_sandbox);
TEST_REPORT();
RETURN_TEST_STATUS;
}