在 MFC 對話方塊的 OnInitDialog() 函式中撰寫讀取文字檔案的程式碼。當資料檔案只有一行時程式正常執行,但若有兩行或以上,程式會在 CStringData* GetData() 處停止,導致當機。
CStdioFile myFile;
CFileException fileException;
if (myFile.Open(_T("data.txt"), CFile::typeText | CFile::modeReadWrite), &fileException) {
myFile.SeekToBegin();
CString str;
while (myFile.ReadString(str)) {
single* fi = new single();
int sec = 0;
CString p;
for (int i = 0; i < str.GetLength(); i++) {
if (str[i] == ',') {
if (sec == 0) // 單號
fi->setNum(p);
else if (sec == 1) {
if (p == "0") fi->setCategory(0);
else fi->setCategory(1);
}
else if (sec == 2) fi->setSendAddr(p);
else if (sec == 3) fi->setSendPhone(p);
else if (sec == 4) fi->setSendNote(p);
else if (sec == 5) fi->setReceiveAddr(p);
else if (sec == 6) fi->setReceivePhone(p);
else if (sec == 7) fi->setReceiveNote(p);
else if (sec == 8) fi->setSendDate(p);
else if (sec == 9) fi->setReceiveDate(p);
else if (sec == 10) {
if (p == "0") fi->setReceived(false);
else fi->setReceived(1);
}
else if (sec == 11) {
if (p == "0") fi->setUnknow(0);
else fi->setUnknow(1);
}
else if (sec == 12) {
int num = _ttoi(p);
fi->setUnknowNote(num);
}
else {
double mon = _wtof(p);
fi->setMoney(mon);
sec = -1;
}
p = "";
sec++;
}
else
p += str[i];
}
tree->insert(fi);
}
}
else {
TRACE("Can't open file %s,error=%u\n", _T("data.txt"), fileException.m_cause);
}
myFile.Close();
程式在處理第二行資料時當機,可能原因包括:
new single() 配置的物件未正確釋放,導致記憶體洩漏或損毀。sec 計數會超出預期範圍,導致存取無效記憶體。CString 內部資料結構損壞:當機堆疊指向 CStringData::GetData(),暗示 CString 物件內部指標異常。str 內容,確認資料格式正確。single 類別的建構子與解構子,確保所有成員變數正確初始化。std::unique_ptr)管理動態配置的 single 物件,避免記憶體洩漏。sec 不超過預期欄位數。CStdioFile myFile;
CFileException fileException;
if (myFile.Open(_T("data.txt"), CFile::modeRead | CFile::typeText, &fileException)) {
CString str;
while (myFile.ReadString(str)) {
// 略過空白行
if (str.IsEmpty()) continue;
std::unique_ptr<single> fi = std::make_unique<single>();
int sec = 0;
CString field;
bool parseError = false;
for (int i = 0; i <= str.GetLength(); ++i) {
// 處理最後一個欄位(無逗號結尾)
if (i == str.GetLength() || str[i] == ',') {
switch (sec) {
case 0: fi->setNum(field); break;
case 1: fi->setCategory(field == _T("0") ? 0 : 1); break;
case 2: fi->setSendAddr(field); break;
case 3: fi->setSendPhone(field); break;
case 4: fi->setSendNote(field); break;
case 5: fi->setReceiveAddr(field); break;
case 6: fi->setReceivePhone(field); break;
case 7: fi->setReceiveNote(field); break;
case 8: fi->setSendDate(field); break;
case 9: fi->setReceiveDate(field); break;
case 10: fi->setReceived(field != _T("0")); break;
case 11: fi->setUnknow(field == _T("0") ? 0 : 1); break;
case 12: fi->setUnknowNote(_ttoi(field)); break;
case 13: fi->setMoney(_wtof(field)); break;
default: parseError = true; break;
}
if (parseError) break;
field.Empty();
++sec;
}
else {
field += str[i];
}
}
if (!parseError && sec == 14) { // 確認欄位數正確
tree->insert(fi.release()); // 交由 tree 管理生命週期
}
else {
TRACE(_T("資料行格式錯誤: %s\n"), str);
}
}
myFile.Close();
}
else {
TRACE(_T("無法開啟檔案: %s, 錯誤碼: %u\n"), _T("data.txt"), fileException.m_cause);
}
透過上述改進,可有效避免記憶體管理錯誤,並增強資料解析的健壯性。