今天測試寫過的一段程式,比較頻繁的出現乙個fread錯誤:
貼**:
int sendchannelinfo(socket_obj *sock)
else
if (postsend(sock, sendbuf) != no_error)
}return 0;
}錯誤描述:讀檔案的時候,fopen正常,得到正確的檔案指標,之後的若干次讀操作正確,但是不確定性的出錯。每次出錯後,count=fread()一句讀取檔案失敗,返回0。feof()返回非0值,表明檔案已經結束。但是,之前根據ftell的結果,檔案還沒結束。
檢查讀取的內容,發現有時候缺檔案中間部分,還有時候缺少檔案結尾。
新增logb處的**,發現ftell()==pos,但是如果沒有後面乙個fseek,出錯;如果加上fseek,正確。
上述函式處於多執行緒環境,但是本身只會被乙個執行緒呼叫執行,之後還有類似的呼叫多次,傳輸多個檔案。
解決辦法和原因:
在logb處新增fseek**,設定檔案指標.
沒有詳細的原因分析,也沒有發現原因.
估計是程式其他部分的執行,使得系統的檔案管理部分出錯,或者是一些記憶體被錯誤修改,造成fp指標的一些引數出錯,無法正確定位下次的讀寫位置.
原因分析:
後來逐行除錯跟蹤分析fp指標的變化,發現在log操作之後,結構體中的乙個指標值發生變化。更進一步的跟蹤顯示,在日誌模組使用了flushall() 函式,該函式強制重新整理所有的緩衝區,導致fp使用的讀緩衝區被重新整理(作廢)。當再次呼叫fread的時候,系統重新讀取檔案,從上次沒有取到緩衝區的部分 開始讀,使得檔案中間部分缺失;當檔案較小的時候,前次讀取就已經到檔案結尾,也就不會有新的資料到達,使得檔案尾缺失。
推測:1、flushall函式關係os的硬碟快取,使得寫緩衝區寫到硬碟,讀緩衝區失效。
2、fread函式實質上是從os的緩衝區讀寫內容,windowsxp的預設緩衝區4kb。fread修改file指標,包含對os緩衝區的偏移資訊的修改。
3、os讀寫硬碟,放到系統緩衝區,修改os自己的io資料結構。
4、flushall不會重置硬碟讀寫的位置資訊,即不修改os的io資料結構;也不影響file指標,包括ftell操作。
5、fseek操作,重新設定硬碟讀寫的位置,修改os的io資料結構,影響file指標。
6、3和4隱含乙個矛盾:os讀寫檔案依賴的是自己的io資料結構,從上次緩衝區讀之後的位置開始操作;但是ftell卻指向應用程式實際讀取到的緩衝區 位置。flushall之後,如4所分析,這兩個資料都不變化。考慮繼續讀寫的情況,由於緩衝區內容失效,os會讀取4096之後的內容,但是應用程式卻 需要file指標指向的單元。這樣,fread操作,讀取到的內容就是os新讀取到緩衝區的內容。如果os緩衝區和應用程式緩衝區大小不一樣,這時候的 fread就返回一組錯誤的資料。
出錯原因分析:
對緩衝機制和重新整理機制還不清楚,沒有深入了解flush對各個元件的影響。
自己遇到的問題:
上面的描述雖然對我的問題沒有幫助,但是值得學習。
fread函式真的有的研究。。。。。。
flushall 函式的用法
flushall 函式 如下所示的乙個非常簡單的程式.1 include 2void main void 3 本意思是從鍵盤接受兩個字元,然後反饋到螢幕上.比如我要輸入a和b,那麼希望得到的結果是now they are a b 但結果卻只顯示了 a 為什麼是這樣的結果呢?因為我們輸入了乙個a後會習...
fread和 fgets的區別
fread 和fgets 的區別 fread 以位元組位計算長度 按照指定的長度和次數讀取資料 遇到結尾或完成指定長度讀取後停止 fgets 整行讀取 遇到回車換行或結尾停止 在文字方式時使用.讀字串函式 fgets 函式的功能是從指定的檔案中讀乙個字串到字元陣列中,函式呼叫的形式為 fgets 字...
fopen 和 fread 的用法
開啟檔案或獲得有關開啟檔案的資訊 說明 1 fileid fopen filename 開啟檔案 filename 以便以二進位制讀取形式進行訪問,並返回等於或大於 3 的整數檔案識別符號。matlab 保留檔案識別符號 0 1 和 2 分別用於標準輸入 標準輸出 螢幕 和標準錯誤。如果 fopen...