客戶端彈出登入視窗,輸入用戶名點擊「確定」後,終端機立即顯示 Segmentation Fault (段錯誤)。程式可正常編譯,運行時崩潰。
代碼宣告 struct hostent *host;,在 do_connect() 中直接使用 host->h_addr,**未呼叫 gethostbyname() 初始化**。導致存取野指標/空指標,觸發段錯誤。
修正:
server_addr = "127.0.0.1";
host = gethostbyname(server_addr);
if (host == NULL) {
// 錯誤處理:顯示「無法解析伺服器位址」
return FALSE;
}
s_in.sin_addr = *((struct in_addr *)host->h_addr);
struct sockaddr_in *remote_addr; 僅宣告指標,未 g_new()/malloc()。accept() 寫入該指標導致非法記憶體寫入。
修正:remote_addr = g_new(struct sockaddr_in, 1);,結束前 g_free(remote_addr);。
fcntl(user.sd, F_GETFL) → user 為陣列,缺少下標。應為 fcntl(user[count].sd, F_GETFL)。
for(j=0;j 缺少終止條件。應為 for(j=0; j < MAX_USERS; j++)。
read() 回傳位元組數 len,需手動添加 read_buf[len] = '\0'; 才能安全作為字串處理 (如 gtk_text_buffer_insert)。
GLib 2.32+ 棄用第三參數 joinable,建議改用 g_thread_new():
g_thread_new("get_message", (GThreadFunc)get_message, NULL);
主函式 gtk_init() 後需初始化執行緒支援:
if (!g_thread_supported()) g_thread_init(NULL);
gdk_threads_init(); // GDK 2.x
gdk_threads_enter(); // 主迴圈前進入
gtk_main();
gdk_threads_leave();
或使用 gdk_threads_add_idle() 安全更新 UI (GTK 3/4 推薦)。
gcc -Wall -Wextra -g -o chat client.c `pkg-config --cflags --libs gtk+-2.0`gdb ./chat → run → 崩潰後 bt (backtrace) 定位崩潰行號。ulimit -c unlimited,事後分析 core dump。valgrind --tool=memcheck ./chat 偵測記憶體錯誤 (未初始化讀取、越界、洩漏)。段錯誤 90% 來自**未初始化指標**、**陣列越界**、**釋放後使用**。本案例中客戶端缺少 gethostbyname() 是核心原因。養成「指標使用前必檢查初始化」、「編譯全開警告」、「gdb/valgrind 例行除錯」習慣,能顯著減少此類低級錯誤。