fscanf 上的大小 4 读取无效

Invalid read of size 4 on fscanf

运行 我的程序通过 valgrind,我在以下代码中收到大小 4 错误的无效读取(我认为在调用 fscanf 的那一行)

重要信息numIntegers 是可以读取的最大整数数量,而 numsInFile 指定文件中存在的整数数量。

我用两者中的最小值来初始化数组。这样做的原因是因为如果 numIntegers100 并且文件中有 22 个整数,我只想要一个大小为 22 的数组。如果 numIntegers 是 22 并且文件中有 100 个整数,我仍然想要一个大小为 22 的数组,因为只能读取 22

这是我的代码:

// Get number of integers (first number)
int numsInFile;
fscanf(fp, "%d", &numsInFile);

// find minimum of numstoread and numintegers and use that as counttouse
    if(numsInFile < numIntegers)
        countToUse = numsInFile;
    else
        countToUse = numIntegers;

// Initialize the integers array with the minimum value as well - since it will only store this many
integers = malloc(sizeof(int) * countToUse);

for(int i = 0; i < numsInFile; i++){
    if(i < numIntegers){
        int currInt;
        if(fscanf(fp, "%d", &currInt) == 1)
            integers[i] = currInt;
        else
            break;
    }
    else
        break;
}

提前感谢任何帮助。我这辈子都想不通为什么我在 valgrind 中遇到这个错误...

代码已编辑 - 不再有错误

// Get number of integers (first number)
int numsInFile;
if( fscanf(fp, "%d", &numsInFile) != 1)
    fprintf(stderr, "Error reading number of integers(first number) from file. Exiting.\n");
    exit(1);
}

// find minimum of numstoread and numintegers and use that as counttouse
    if(numsInFile < numIntegers)
        countToUse = numsInFile;
    else
        countToUse = numIntegers;

// Initialize the integers array with the minimum value as well - since it will only store this many
integers = malloc(sizeof(int) * countToUse);

for(int i = 0; i < countToUse; i++){
    int currInt;
    if(fscanf(fp, "%d", &currInt) == 1)
        integers[i] = currInt;
    else{
        fprintf(stderr, "Error loading integer array in countAndSort(). Exiting.\n");
        exit(1);
}

您为 countToUse 个整数分配了 space

integers = (int*)malloc(sizeof(int) * countToUse);

然后遍历numsInFile,然后检查ornumIntegers,这是错误的,你不检查第一个fscanf()的return值或者你的 malloc().

下面不会让valgrind报错

/* Get number of integers (first number) */
int numsInFile;

if (fscanf(fp, "%d", &numsInFile) != 1)
    doSomethingAboutIt_ButDoNotContinue();
/* find minimum of numstoread and numintegers and use that as counttouse */
if (numsInFile < numIntegers)
    countToUse = numsInFile;
else
    countToUse = numIntegers;
/*
 * Initialize the integers array with the minimum value as well
 * since it will only store this many 
 */
integers = malloc(sizeof(int) * countToUse);
if (integers == NULL)
    doSomethingAboutIt_ButDoNotContinue();
for (int i = 0 ; i < numsInFile ; i++)
{
    if (i < countToUse) /* You allocated enough space for countToUse int's */
    {
        int currInt;

        if (fscanf(fp, "%d", &currInt) == 1)
            integers[i] = currInt;
        else
            break;
    }
    else
        break;
}

当然有更好的方法,从 0countToUse 循环,但我只是想指出您的代码有什么问题。

这些技巧应该可以帮助您提高技能,据我所知,这些技巧很好

  1. 始终检查函数中的 returned 值是否有错误,例如 malloc() returns NULL 失败,而你没有不检查它。

    这种情况发生的可能性很小,但并非不可能,所以检查一下是明智的。

  2. 使用编译器警告,它们可以帮助您解决那些通常难以发现的小错误。

  3. 当使用 valgrind 编译你的程序时,使用调试信息而不进行优化,正如@JohnBollinger 指出的那样,这将帮助你知道问题出在哪一行。

    这是我使用的典型编译器命令

    gcc -Wall -Wextra -Werror -O0 -g3
    

    调试时它是防止愚蠢错误的极好方法,如果您关心可移植性,也可以添加 std=c99,如果您真的想净化代码,也可以添加 -pedantic