【问题标题】:valgrind - Address is 2 bytes before a block of size 16 alloc'dvalgrind - 地址是分配大小为 16 的块之前的 2 个字节
【发布时间】:2019-01-20 13:00:43
【问题描述】:

我在试图理解为什么 valgrind 告诉我我超出了 char *array 的范围时遇到了一些问题。

每当我尝试从 nul 字节之前开始向后迭代数组时。它向我抛出了我正在访问不应该访问的内存的错误。

这是我的第一个函数:

char *ReadLineFile(FILE *infile) {
    int initSize = 16;
    char *string = NULL;
    string = malloc(sizeof(char) * initSize);
    if(string == NULL){
        exit(-1);
    }

    char val;
    int valSize = 0;
    while((val = fgetc(infile)) != EOF){
        if(val == '\n'){
            break;
        }

        if(valSize == initSize){
            initSize *= 2;
            string = realloc(string, initSize * sizeof(char));
        }

        string[valSize++] = val;
    }

    if(valSize == initSize){
        initSize++;
        string = realloc(string, initSize * sizeof(char));
    }

    string[valSize++] = '\0';

    return trimString(string);
}

这是我的第二个功能:

char *trimString(char *string) {
    int start = 0;
    int end = strlen(string);

    while(string[start] == ' '){start++;}
    while(string[end-2] == ' '){end--;}  // the [end-2] causes the error in valgrind

    int trimLen = end - start;
    char *trimmedStr = malloc(sizeof(char) * (trimLen + 1));
    if(trimmedStr == NULL){
        exit(-1);
    }

    int i = 0;
    while(start != end){
        trimmedStr[i] = string[start];
        i++; start++;
    }

    trimmedStr[i] = '\0';
    free(string);

    return trimmedStr;
}

Valgrind 错误:

==3809== Invalid read of size 1
==3809==    at 0x1090D5: trimString (myio.c:129)               
==3809==    by 0x109080: ReadLineFile(myio.c:120)
==3809==    by 0x108C54: main (driver2.c:29)
==3809==  Address 0x522e03e is 2 bytes before a block of size 16 alloc'd
==3809==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload/memcheck-amd64-linux.so)
==3809==    by 0x108F91: ReadLineFile(myio.c:90)
==3809==    by 0x108C54: main (driver2.c:29)

我希望 valgrind 不会出现错误,因为我在字符串中分配了足够的内存,而是告诉我,当我尝试向后迭代数组时,我正在尝试访问我不应该访问的内存。我想了解是什么原因造成的,因为我花了几个小时试图找出这个错误。谢谢!

【问题讨论】:

  • char val 不能包含 EOF,因为 EOF 需要 shortint... 使用 int val 来检测 EOF。
  • while(string[start] == ' '){start++;} 可能超出字符串的末尾,使用while(start < end && string[start] == ' ') ++start; 同样适用于while(string[end-2] == ' '){end--;},使用while(end > start && string[end-1] == ' '){end--;}
  • 终于!这解决了我的问题。在文件的末尾,有一个只包含一个空字节的空字符串,这导致数组超出范围。非常感谢你!也感谢您澄清 val 的数据类型!
  • 我很高兴能帮上忙。随意投票/接受我的回答;-)
  • 完成,非常感谢!

标签: c valgrind


【解决方案1】:

如果该行只是空格或空行怎么办?

在这种情况下,while(string[end-2] == ' '){end--;} 可能会到达行首并继续“向后”行走。

考虑测试行/字符串的限制。另外,为什么-2?为什么不-1?即:

while(end > start && string[end - 1] == ' ') --end;

这种方法可以防止您“走”太远。

旁注

EOF 标记不是有效字节(不在 0-255 值范围内)。如果是,它可能是文件中间的有效值。

因此,EOF 不能包含在 char 中,您无法测试 char 是否包含 EOF。使用int val 而不是char val

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 2023-03-03
    • 2018-08-21
    • 1970-01-01
    • 2015-03-17
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多