一些基础组件
This commit is contained in:
+82
-47
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user