簡體   English   中英

為什么 Valgrind 抱怨 fgets?

[英]Why Valgrind complains about fgets?

我有一個簡單的 C 代碼。

主文件

int main() {
    FILE *stream = fopen("../input.txt", "r");
    cube test_cube;
    cube_initialization(&test_cube, stream);

/* and some code with free memory which is not needed to understand the situation */

}

立方體.c

/* just the function valgrind complains about */

void cube_initialization(cube *cube, FILE *input_file) {
    int side_length;
    char buffer[BUF_SIZE];
    char waste_buffer[BUF_SIZE];


    fgets(buffer, BUF_SIZE, input_file);
    fgets(waste_buffer, BUF_SIZE, input_file); /* empty line */
    side_length = (int) strtol(buffer, NULL, 10);
    cube->side_length = side_length;
    cube->cube_array = malloc(side_length * sizeof(int **));
    int z;
    for (z = 0; z < side_length; z++) {
        cube->cube_array[z] = malloc(side_length * sizeof(int *));
        int y;
        for (y = 0; y < side_length; y++) {
            cube->cube_array[z][y] = malloc(side_length * sizeof(int));
        }
    }
}

和 valgrind 輸出

==8251== Invalid read of size 4
==8251==    at 0x48F3727: fgets (iofgets.c:47)
==8251==    by 0x1093C2: cube_initialization (cube.c:11)
==8251==    by 0x10928D: main (main.c:11)
==8251==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==8251== 
==8251== 
==8251== Process terminating with default action of signal 11 (SIGSEGV)
==8251==  Access not within mapped region at address 0x0
==8251==    at 0x48F3727: fgets (iofgets.c:47)
==8251==    by 0x1093C2: cube_initialization (cube.c:11)
==8251==    by 0x10928D: main (main.c:11)
==8251==  If you believe this happened as a result of a stack
==8251==  overflow in your program's main thread (unlikely but
==8251==  possible), you can try to increase the size of the
==8251==  main thread stack using the --main-stacksize= flag.
==8251==  The main thread stack size used in this run was 8388608.
==8251== 
==8251== HEAP SUMMARY:
==8251==     in use at exit: 0 bytes in 0 blocks
==8251==   total heap usage: 1 allocs, 1 frees, 488 bytes allocated
==8251== 
==8251== All heap blocks were freed -- no leaks are possible
==8251== 
==8251== For lists of detected and suppressed errors, rerun with: -s
==8251== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

我不明白為什么 Valgrind 抱怨fgets() 我從文件中讀取數據並使用fgets和指向 big buffer(256) 的指針,但它只需要我讀取大約 1-6 個符號的短行(我需要 fgets,因為它在行尾找到 '\\n' 時停止) . 也許問題在於 fgets() 嘗試讀取 256 個符號的行並在 1-5 和 '\\n' 之后停止?

Valgrind 抱怨非法地址0x0訪問:

地址 0x0 未被堆棧、malloc 或(最近)釋放

在您的fgets()電話中

fgets(buffer, BUF_SIZE, input_file);

buffer參數很好,因為它是在堆棧中分配的。 唯一負責的可以是input_file參數,來自main() 該參數是從fopen()調用獲得的流。 在傳遞給cube_initialization()之前你沒有檢查它!

檢查它,然后理解為什么它返回NULL(可能你試圖打開一個不存在的路徑)。

int main() {
    FILE *stream = fopen("../input.txt", "r");
    cube test_cube;
    if( stream != NULL )
    {
        cube_initialization(&test_cube, stream);

        /* Continue execution*/
    }
}

Valgrind 抱怨fgets()讀取無效。 問題不太可能是目標數組的大小,這可能會觸發無效寫入,但確實是一個BUF_SIZE字節的數組,您將其記錄為合理的 256 值。問題更可能與流指針有關,它Valgrind 報告的可能為空:

Address 0x0 is not stack'd, malloc'd or (recently) free'd`

您應該修復代碼中潛在的未定義行為:

  • 驗證fopen()返回了有效的FILE* ,以避免嘗試從input_file讀取時出現未定義的行為。
  • 驗證fgets()成功(不返回NULL ),以避免從目標數組讀取時出現未定義的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM