我有这段代码:
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要么。
第二次编辑,我将展示更多我的代码。
这是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;
}
编辑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 :(得分:1)
我认为这可能是一种误报。
fgets
在内部使用memchr
来检查是否有新行。您的平台memchr
是一个高度优化的汇编例程(名称表示它专门针对Haswell架构进行了优化),它一次读取32个字节以定位目标字符(可能使用一些SSE指令来执行此操作)。在缓冲区结束时,memchr
在150字节分配结束时运行,并且valgrind会抱怨。
这是完全安全的;由于页面分配大小(至少)为4096字节,因此memchr
如果坚持对齐的32字节边界,则不可能触及坏内存。如果它在未初始化的内存中找到目标字符,它可能会检测到找到的字符超过了它应该搜索的字符串的结尾,并在那种情况下返回正确的结果。
我会忽略这个错误。 Valgrind偶尔会产生误报;考虑获取或制作特定于平台的抑制文件,以自动忽略这些类型的错误警报。