c - 使用 fscanf 时调试 seg 错误时出现问题

标签 c segmentation-fault valgrind scanf

我在下面的 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 文件读入值:

(i 初始化为 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)

最佳答案

如果你有一个字母或标点符号,而你应该有一个数字,那么你就会陷入无限循环,并且会溢出你分配的人员数组的边界。您应该检查:

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() 的状态之外)。

哦……你分配人员;您正在阅读 inPersons...哪个是正确的?

我想我会编写一个函数来调用 fscanf() 并检测和报告错误,然后从 while 循环中调用它:

while (i < SIZE && get_person(&persons[i]) != EOF)
   ...

或者:

while (i < SIZE && get_person(&inPersons[i]) != EOF)
   ...

这还允许您从 fscanf() 切换到 fgets()sscanf()getline( )sscanf()

关于c - 使用 fscanf 时调试 seg 错误时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18971793/

相关文章:

python - 素数生成器中的段错误

multithreading - Vala:当加入的线程未被引用时读取无效

c - 释放所有由 malloc(), realloc() 在 C 中分配的内存

C - 函数内的动态分配/重定位

c++ - 使用 Visual Studio 在 C++ 应用程序中查找内存泄漏

创建循环链表

c - 在 c 中将 vector 转换为字符串

c - gcc 在 Cygwin 中失败并显示 "undefined reference",但引用存在于链接库中

c - 如何访问结构体中的结构体数组?

c - 类型转换为其中包含另一个结构 ptr 的结构