程式執行到 system("cls") 前崩潰,彈窗提示「記憶體無法為 read/write」,且伴隨 360 誤報、CMD 無法關閉等連鎖異常。核心原因在於 getTextFileContent 與 getFileSize 兩個函數的嚴重 Bug。
// 原碼 錯誤
long size = (fseek(f, 0L, SEEK_END) != 0) ? (ftell(f)) : -1;
// fseek 成功返回 0,失敗返回非零。
// 原碼在「成功時」執行 ftell,但條件寫成 != 0,導致成功時返回 -1,失敗時才取 ftell (未定義行為)。
修正:
long size = (fseek(f, 0L, SEEK_END) == 0) ? ftell(f) : -1;
// 或更清寫:
if (fseek(f, 0L, SEEK_END) != 0) return -1;
long size = ftell(f);
rewind(f);
// 原碼片段
char *ptr = (char*)malloc(size + chLen);
char *block = ptr;
// ...
while((c = fgetc(fp)) != EOF) {
ch = (char)c;
memcpy(ptr, &ch, chLen);
(int)ptr += chLen; // 嚴重錯誤:將指標強轉為 int 再加法,64 位元系統截斷高 32 位,指標變野指標!
}
memcpy(ptr, &endC, chLen); // 寫入結束符時 ptr 已失效,導致堆損壞
修正: 直接使用指標算術 ptr += chLen; (指標自動按類型大小遞增,此處為 1),絕不可轉為整數運算。
// 原碼
text = (text == NULL) ? "" : text;
// 若 text 為 NULL,text 指向唯讀字串常量區 "",後續 free(text) 嘗試釋放常量區記憶體 → 崩潰。
修正: 直接判斷 if (text == NULL) text = ""; 但後續不可 free(text);或分配一份副本 strdup("")。最佳做法:if (!text) text = strdup(""); 並確保最後 free(text) 安全。
char* getTextFileContent(const char *path) {
FILE *fp = fopen(path, "rb"); // 二進制模式避免換行轉換影響大小
if (!fp) return NULL;
if (fseek(fp, 0L, SEEK_END) != 0) { fclose(fp); return NULL; }
long size = ftell(fp);
rewind(fp);
char *buf = (char*)malloc(size + 1);
if (!buf) { fclose(fp); return NULL; }
size_t read = fread(buf, 1, size, fp); // 一次性讀取,效率高且無指標運算風險
buf[read] = '\0';
fclose(fp);
return buf;
}
mStrCat 使用 memmove + strcat,若 str1 未以 \0 結尾會越界。建議改用 snprintf 或標準 strdup + strcat 並檢查長度。getTD() 中 struct tm tmptm = {0,0,0,9,5,2015-1900}; 月份欄位 tm_mon 為 0-11,5 代表 6 月,正確;但 mktime 依賴本地時區,跨時區部署需注意。這起崩潰是典型的 C 語言手動記憶體管理陷阱組合拳:fseek 邏輯反 → 分配錯誤大小 → 指標強轉 int 運算 → 寫入越界破壞堆元資料 → free 觸發崩潰。改用 fread 一次性讀取、指標原生算術、嚴格檢查分配/釋放配對,即可根治。