У меня есть этот код: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
(a) что происходит, когда 'strchr (buffer, '')' возвращает NULL? (b) Вызов 'getRoomSize' является подозрительным, но вы не указали код для него; (c) «убедитесь, что указатель на файл malloced» не имеет смысла, нет проблем с 'FILE * fp', но, возможно, у вас была ошибка в вашей функции' openFile'; (d) не бросать 'argv [1]', исправить интерфейс 'openFile'; (e) опубликуйте [MCVE] (http://stackoverflow.com/help/mcve) в следующий раз, так как в этом коде слишком много неизвестных. –
Я бы предположил, что на основе сообщения valgrind, что функция 'removeNewLine' также удаляет нулевой ограничитель –
@MattMcNabb Извините за отсутствие информации, я обновил сообщение. Также функция 'removeNewLine' просто заменяет' \ n' на '\ 0'. – MortalMan