2011-09-16 144 views
2

我寫以下代碼:信號11(SIGSEGV)

FILE *book; 
wchar_t bufferln[FILE_READ_BUFFER]; 
wchar_t buffer[FILE_READ_BUFFER]; 
book = fopen(file, "r"); 
if(book == NULL){ 
    perror("Es ist ein Fehler beim lesen des Buches aufgetreten"); 
    return EXIT_FAILURE; 
} 
while(fgetws(buffer, FILE_READ_BUFFER, book) != NULL){ 
    if(wcscmp(buffer, L"\n") == 0){ 
     bufferln[0] = L'\0'; 
     continue; 
    } 
    buffer[wcsnlen(buffer, FILE_READ_BUFFER)-1] = L' '; 
    wcsncat(bufferln, buffer, FILE_READ_BUFFER); 
} 
return EXIT_SUCCESS; 

它崩潰與SIGSEGV。我跑Valgrind的,顯示如下:

==11251== Conditional jump or move depends on uninitialised value(s) 
==11251== at 0x40BD5CF: wcsncat (wcsncat.c:36) 
==11251== by 0x804865D: read_book (book.c:18) 
==11251== by 0x804872B: main (main.c:19) 
==11251== Uninitialised value was created by a stack allocation 
==11251== at 0x80485B7: read_book (book.c:3) 
==11251== 
==11251== Invalid read of size 4 
==11251== at 0x40A58E2: fgetws (iofgetws.c:52) 
==11251== by 0x804867D: read_book (book.c:12) 
==11251== by 0x6D: ??? 
==11251== Address 0x65 is not stack'd, malloc'd or (recently) free'd 
==11251== 
==11251== 
==11251== Process terminating with default action of signal 11 (SIGSEGV) 
==11251== Access not within mapped region at address 0x65 
==11251== at 0x40A58E2: fgetws (iofgetws.c:52) 
==11251== by 0x804867D: read_book (book.c:12) 
==11251== by 0x6D: ??? 
==11251== If you believe this happened as a result of a stack 
==11251== overflow in your program's main thread (unlikely but 
==11251== possible), you can try to increase the size of the 
==11251== main thread stack using the --main-stacksize= flag. 
==11251== The main thread stack size used in this run was 8388608. 

我認爲這個問題以某種方式與我wcsncat的使用(寫入*本書內存也許?),但爲什麼呢? 我想逐段閱讀文檔(UTF-8),然後執行不在此代碼中的內容。

回答

1

什麼能發生的事情是,你的wcsncat(),它爲每個文件的作用:

「 描述 的wcsncat()函數將不超過字符串的第n個字符更多指向WS2到如果一個NULL字符出現在ws2前n個字符中,所有到NULL字符的字符都會附加到ws1中,ws2的第一個字符將覆蓋ws1的終止NULL字符,NULL結尾字符是總是附加到的結果,以及如果用於複製重疊的對象,該行爲是未定義。 「

因此,它通過覆蓋第一次出現NULL字符開始繼續追加到bufferln。因此,如果if(wcscmp(buffer,L「\ n」)== 0)返回FALSE,您將最終超出您分配的FILE_READ_BUFFER緩衝區並將文件泄漏到bufferln邊界之外,最終可能會損壞堆棧。

在大多數情況下,棧向下增長,它必須達到實際上的錯,因爲訪問的第一個2頁的虛擬地址的頁面是不允許在大多數系統上的一些地區。這是一個有爭議的問題,爲什麼它在那裏出錯。但主要的原因是你必須在讀取數據之後嘗試寫入數據,因爲你的讀寫緩衝區長度相同。

HTH

+0

我希望wcsncat只能追加x個字符,直到w1達到n個字符。解決了,謝謝! –

0

如果該行是空的(\ n變由\ 0取代),字符串的長度爲空,和strlen的(±)-1-緩衝以下點。

編輯: 我理解錯了;你只是追加太多。增加緩衝區大小,讀取較短的行,或兩者。 並避免strcat();

+0

我用wcsncat至極需要緩衝區大小作爲參數,進一步我只讀FILE_READ_BUFFER跡象(相當於1000),並在每一個負責處理字符串函數中使用相同的常量。你的意思是什麼? –

+0

對不起,我錯了。 [我只是恨* str *貓()!只要繼續計數...]。喬納森可能是正確的:緩衝區只是未初始化。 – wildplasser

2

您不初始化bufferln,因此當您將新行連接到未初始化數據的末尾時(wcsncat()),您不知道代碼要寫入的位置。

您還在輸入緩衝區buffer末尾的空終止符上寫了一個(寬)空間,所以您不知道要將什麼複製到隨機位置;複製將在下一次遇到寬NUL時停止。

相關問題