2015-04-07 2 views
1

У меня есть этот код:Valgrind жалуется на призыв fgets

int main(int argc, char const *argv[]) 
{ 
    FILE *fp = NULL; 
    char *buffer = malloc(sizeof(char) * 150); 
    char roomElements[150]; 
    char *roomSize = NULL; 
    int i = 1; 
    int *size = NULL; // does this need to be malloced? 
    char input = '\0'; 

    check(argc == 2, "Please enter two arguments"); 

    fp = openFile((char*)argv[1], "r"); 

    initscr(); // ncurses 
    noecho(); 


    /*Draws rooms and items*/ 
    while (fgets(buffer, 150, fp)) { // line 25 
     removeNewLine(buffer); 
     strcpy(roomElements, strchr(buffer, ' ')); 
     roomSize = strtok(buffer, " "); // get the room size 
     size  = getRoomSize(roomSize, i); // convert room size to int pointer 
     drawRoom(size, i); // draw the room 
     tokenizeRoom(roomElements, i); // draw the elements 
     i++; 
     free(size); 
    } 

    /*This is the user input loop*/ 
    do { 
     input = getch(); 
     getInput(input); 
    } while (input != 'q'); 

    free(buffer); 
    fclose(fp); 
    endwin(); 

    return 0; 
error: 
    return -1; 
} 

Valgrind выход:

==74014== Memcheck, a memory error detector 
==74014== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==74014== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info 
==74014== Command: ./bin/rogue assets/room.txt 
==74014== 
==74014== Invalid read of size 32 
==74014== at 0x10043EC1D: _platform_memchr$VARIANT$Haswell (in /usr/lib/system/libsystem_platform.dylib) 
==74014== by 0x10023080A: fgets (in /usr/lib/system/libsystem_c.dylib) 
==74014== by 0x100000E10: main (main.c:25) 
==74014== Address 0x100918a40 is 32 bytes before a block of size 4,096 in arena "client"              
==74014== Conditional jump or move depends on uninitialised value(s) 
==74014== at 0x10043EC7A: _platform_memchr$VARIANT$Haswell (in /usr/lib/system/libsystem_platform.dylib) 
==74014== by 0x10023080A: fgets (in /usr/lib/system/libsystem_c.dylib) 
==74014== by 0x100000E10: main (main.c:25) 
==74014== Uninitialised value was created by a heap allocation 
==74014== at 0x100008601: malloc (vg_replace_malloc.c:303) 
==74014== by 0x100233836: __smakebuf (in /usr/lib/system/libsystem_c.dylib) 
==74014== by 0x100236E99: __srefill0 (in /usr/lib/system/libsystem_c.dylib) 
==74014== by 0x100236F94: __srefill (in /usr/lib/system/libsystem_c.dylib) 
==74014== by 0x1002307DA: fgets (in /usr/lib/system/libsystem_c.dylib) 

Что я могу делать неправильно? Все инициализировано, я в недоумении. Никакие другие ответы на эту тему не помогают мне. Я не уверен, почему он жалуется на вызов fgets.

2nd edit, я покажу еще несколько своих кодов. Вот openFile()

FILE *openFile(char *file, char *mode) { 
    FILE *fp = NULL; 

    fp = fopen(file, mode); 

    check(fp, "Could not open %s", file); 

    return fp; 
} 

Вот getRoomSize

int *getRoomSize(char *size, int roomNum) { // rows x columns 
    int row, col; 
    char strRow[5], strCol[5]; 
    int *roomSize = malloc(sizeof(int) * 2); 

    check(roomNum < 7 && roomNum > 0, "Invalid room to be drawn"); 

    /*Convert string to int*/ 
    strcpy(strRow, strtok(size, "X")); 
    strcpy(strCol, strtok(NULL, "X")); 
    row = atoi(strRow); 
    col = atoi(strCol); 

    roomSize[0] = row; 
    roomSize[1] = col; 

    return roomSize; 
} 

EDIT 3: Вот мой MCVE. Он воспроизводит условный переход и неинициализированное значение ошибки:

int main(int argc, char const *argv[]) 
{ 
    char *buffer= malloc(sizeof(char) * 150); 
    char roomElements[300] = {0}; 
    int i = 1; 
    FILE *fp = fopen(argv[1], "r"); 

    if (!fp) { 
     printf("no\n"); 
     exit(0); 
    } 

    while (fgets(buffer, 150, fp)) { 
     strcpy(roomElements, strchr(buffer, ' ')); 
     i++; 
    } 

    free(buffer); 
    return 0; 
} 

Файл представляет собой .txt файл, содержащий эту линию в 6 раз: 15X20 dn2 de10 dw11 g4,2 m10,17 M12,7 M4,9 p11,14 w10,10

+0

(a) что происходит, когда 'strchr (buffer, '')' возвращает NULL? (b) Вызов 'getRoomSize' является подозрительным, но вы не указали код для него; (c) «убедитесь, что указатель на файл malloced» не имеет смысла, нет проблем с 'FILE * fp', но, возможно, у вас была ошибка в вашей функции' openFile'; (d) не бросать 'argv [1]', исправить интерфейс 'openFile'; (e) опубликуйте [MCVE] (http://stackoverflow.com/help/mcve) в следующий раз, так как в этом коде слишком много неизвестных. –

+0

Я бы предположил, что на основе сообщения valgrind, что функция 'removeNewLine' также удаляет нулевой ограничитель –

+0

@MattMcNabb Извините за отсутствие информации, я обновил сообщение. Также функция 'removeNewLine' просто заменяет' \ n' на '\ 0'. – MortalMan

ответ

1

Я думаю, что это может быть ложной тревогой.

fgets использует memchr внутренне, чтобы проверить, есть ли еще символ новой строки. Ваша платформа memchr - это высоко оптимизированная процедура сборки (название указывает, что она специально оптимизирована для архитектур Haswell), которая считывает 32 байта за раз, чтобы найти целевой символ (возможно, используя некоторые инструкции SSE для этого). В конце вашего буфера memchr запускается с конца вашего 150-байтового распределения, и жалобщик жалуется.

Это абсолютно безопасно; memchr не может коснуться плохой памяти, если он придерживается выровненных 32-байтных границ, так как размер выделения страницы (по крайней мере) 4096 байт. Если он найдет целевой символ в неинициализированной памяти, он предположительно обнаружит, что расположенный персонаж находится за концом строки, которую он должен был искать, и вернет правильный результат в этом случае.

Я проигнорировал бы эту ошибку. Valgrind иногда производит ложные срабатывания; рассмотрите возможность получения или создания файла ограничений для конкретной платформы, чтобы автоматически игнорировать эти виды ложных тревог.

+0

Интересно! Можно ли игнорировать все ошибки? – MortalMan

+0

Ну, вы, вероятно, можете игнорировать ошибки, возникающие из 'memchr' - в частности, недопустимое чтение формата 32, последующую неинициализированную ошибку перехода и информационное сообщение malloc впоследствии. Другие ошибки могут быть еще важны - не игнорируйте все! – nneonneo

+0

Конечно, я не буду игнорировать все! У меня есть вопрос, который я задал сегодня, который включает файлы supp, надеюсь, я смогу понять, как создать файл supp. – MortalMan

Смежные вопросы