半天時間找到原因卻仍未解決的Bug

2021-08-22 04:16:11 字數 1585 閱讀 6263

半天時間找到原因卻仍未解決的bug

在乙個巨大的資料檔案作為輸入時, 出現了乙個assert斷言錯誤.

花了半天時間跟蹤**, 費盡心思找到了錯誤的**,

可是一時間也沒有解決的辦法, 只能打個臨時補丁.

類裡面有個成員變數

std::ofstream m_ofs;

在某個方法裡面的斷言警告:

assert(!m_ofs);

流操作之後都有乙個狀態判斷:

if (!m_ofs)

為什麼會有錯誤的流狀態?

但是open()操作後判斷失敗沒有關閉流.

m_ofs.open(spath);

if (!m_of)

表面上看是ofstream::open()開啟檔案出錯了.

open()出錯時只寫了一條日誌, 沒做處理.

這個ofstream物件m_ofs不是臨時物件, 而是類內嵌物件.

下一次使用時, 發現m_ofs處於已開啟狀態, 而流狀態是錯誤的,

以為open()失敗後檔案會處於關閉狀態, 看來是錯誤的.

open()失敗後加了乙個close()試了試,還是有流錯誤。

open()為什麼會出錯? strerror(errno)顯示"no error".

以為是errno沒有正確指示錯誤, 再跟蹤進入open()**, 發現open()其實是成功了.

m_ofs是在open()之前就已經fail了(檢視內部狀態state=2, 即failbit位).

一定是上次close()後failbit並沒有清除.

close()成功情況下, 會執行clear(), 但有可能close()失敗.

新增clear()在所有close()之前.

可是failbit象是憑空出現, clear()並沒有起作用.

回憶歷史**, 原來只有臨時變數的流, 用完就自動關閉了.

而為了對付頻繁的同一檔案開啟, 流物件改為了內部成員變數.

而流的宿主類間接地是另乙個類的成員變數, 該類是某stl容器類的元素.

問題就在這裡了, stl容器類會使用其元素類的拷貝建構函式來複製元素.

一定是ofstream通過這樣的複製後產生了錯誤的狀態.

而宿主類及其上層也沒有提供拷貝建構函式, 只有預設的淺拷貝.

如果沒有這個流, 這些類都是一些簡單資料類, 完全可以使用預設的位元組拷貝.

淺拷貝不行, 深拷貝不能, 結果是找到原因, 卻不知如何修改.

只能暫時恢復為臨時流變數.

不過最終還應該支援大量的檔案開啟關閉操作, 不知怎麼辦.

心得:

* 沒有必要就不要儲存乙個流變數,使用臨時變數可保證檔案開啟與關閉是成對的。

* stl容器最好只存放簡單資料,可避免自定義拷貝建構函式。

如果元素類較複雜,應考慮使用指標,因為有可能今後的修改後使元素類更複雜。

* ofstream::close()可能不會清除錯誤狀態,並可能置failbit,如未開啟就關閉。

上面的clear()應加在close()之後。

問題:* 如何新增單元測試,使得乙個類保證為簡單資料類,或保證stl容器可安全使用?

* 不能實現深拷貝時,有沒有辦法解決淺拷貝問題?

這是標題啊,找了半天沒找到

健康博文在瞎寫嘛?主題呢?團隊協作幹專案 回歸混沌 太極 學以致用 兩儀 效率 產品 產能 產出 三才 生活 工作 價值 成就感 喜悅感 幸福感 四象 太陰 太陽 少陰 少陽?五行 金 木 水 火 土 六合 十二生肖六合?七星 樞 天璇 天璣 天權 玉衡 開陽 搖光?八卦 幹天,坤地,坎水,離火,震...

mysql當天時間和前一天時間

獲取當前的年月日,我使用的是 curdate 下一天或者前一天 curdate 1curdate 1 這是錯誤的寫法 mysql官網也是不承認時間直接相加減的,雖然會將當前時間轉換為20160802,這時候就是比較這一串字元,mysql官網是不承認用這種方式比較時間大小的正確的sql語句 selec...

肯定搜了半天才找到這裡吧

名稱 規格型號 主計量主數量 廠商板卡 cpci429 16t16r 6495 122 423 423件1 ballard 線纜 10ft雙頭pl75短截線 16014件4 ballard 4頭匯流排耦合器 17014件4 ballard a429 usb 8r4t cp ua1430件1 ball...