我在下面的fscanf行中遇到了分段错误。我添加了每个变量的字符宽度来尝试修复它,所以我不明白它为什么会出错。
我从CSV文件读取结构数组。
结构是:
typedef struct Person
{
int ID;
int salary;
int deleted;
char salutation[4];
char firstName[21];
char surName[31];
char job[16];
} Person;
我声明了结构数组:
Person* persons;
persons = (Person*)malloc(SIZE * sizeof(Person));
然后使用while循环将CSV文件读入值:
(我初始化为0)
while(fscanf(f, "%d,%3[^,],%20[^,],%30[^,],%15[^,],%d,%d", &inPersons[i].ID, inPersons[i].salutation, inPersons[i].firstName, inPersons[i].surName, inPersons[i].job, &inPersons[i].salary, &inPersons[i].deleted)!=EOF)
{
newID = inPersons[i].ID;
i++;
}
在fscanf语句中发生了段错误。我对valgrind没有经验,但它给了我这行错误:
==16810== Invalid write of size 4
==16810== at 0x578215: _IO_vfscanf (in /lib/libc-2.12.so)
==16810== by 0x585368: __isoc99_fscanf (in /lib/libc-2.12.so)
==16810== by 0x8048951: loadDb (Database.c:23)
==16810== by 0x8048711: menu (Menu.c:37)
==16810== by 0x804861E: main (main.c:6)
==16810== Address 0x27230128 is not stack'd, malloc'd or (recently) free'd
我也在同一条线上得到这些Valgrind错误:
==18457== Use of uninitialised value of size 4
==18457== at 0x405A215: _IO_vfscanf (in /lib/libc-2.12.so)
==18457== by 0x4067368: __isoc99_fscanf (in /lib/libc-2.12.so)
==18457== by 0x8048943: loadDb (Database.c:23)
==18457== by 0x8048711: menu (Menu.c:37)
==18457== by 0x804861E: main (main.c:6)
==18457== Process terminating with default action of signal 11 (SIGSEGV)
==18457== Access not within mapped region at address 0x5C5E4128
==18457== at 0x405A215: _IO_vfscanf (in /lib/libc-2.12.so)
==18457== by 0x4067368: __isoc99_fscanf (in /lib/libc-2.12.so)
==18457== by 0x8048943: loadDb (Database.c:23)
==18457== by 0x8048711: menu (Menu.c:37)
==18457== by 0x804861E: main (main.c:6)
答案 0 :(得分:1)
如果你有一个字母或标点字符,你应该有一个数字,你有一个无限循环,你溢出你分配的人数组的界限。你应该检查:
while (i < SIZE && (num = fscanf(f, "...", ...)) == 7)
{
...process valid input...
}
...consider what to do here, using `num` to distinguish between EOF and failed conversions...
valgrind
无法识别记忆的事实令人费解。您已经采取了大部分相关步骤来确保不会出现缓冲区溢出(除了正确检查fscanf()
的状态之外的所有步骤)。
哦......你分配persons
;你正在阅读inPersons
......这是正确的吗?
我想我会编写一个函数来调用fscanf()
并检测并报告错误,然后从while
循环中调用它:
while (i < SIZE && get_person(&persons[i]) != EOF)
...
或:
while (i < SIZE && get_person(&inPersons[i]) != EOF)
...
这也允许您从fscanf()
切换到fgets()
和sscanf()
,或getline()
和sscanf()
。