【问题标题】:Write and read errors with Valgrind使用 Valgrind 写入和读取错误
【发布时间】:2020-01-19 13:43:52
【问题描述】:

我尝试将整数转换为二进制格式,我希望结果为 char*,所以我有以下代码:

unsigned int_to_int(unsigned k) {
    if (k == 0) return 0;
    if (k == 1) return 1;                       /* optional */
    return (k % 2) + 10 * int_to_int(k / 2);
}

char* tab_binaire(int nb){
    char* str = (char*) malloc(sizeof(char)*8);
    sprintf(str, "%d", int_to_int(nb));
    int zeroManquant = 8-strlen(str);V
    char* res= (char*) malloc(zeroManquant*sizeof(char));
    for (int i = 0; i < zeroManquant; i++) {
        res[i]='0';
    }
    strcat(res,str);
    free(str);
    str=NULL;
    return res;
}

我已经尝试将退出字符放在字符串的末尾,但我总是把错误放在一边。 这是我的错误:

==10789== Invalid read of size 1
==10789==    at 0x483B924: strcat (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10789==    by 0x1097C3: tab_binaire (automate.c:145)
==10789==    by 0x10983F: main (automate.c:161)
==10789==  Address 0x4a54ae4 is 0 bytes after a block of size 4 alloc'd
==10789==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10789==    by 0x109787: tab_binaire (automate.c:140)
==10789==    by 0x10983F: main (automate.c:161)

==10789==
==10789== Invalid write of size 1
==10789==    at 0x483B940: strcat (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10789==    by 0x1097C3: tab_binaire (automate.c:145)
==10789==    by 0x10983F: main (automate.c:161)
==10789==  Address 0x4a54ae4 is 0 bytes after a block of size 4 alloc'd
==10789==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10789==    by 0x109787: tab_binaire (automate.c:140)
==10789==    by 0x10983F: main (automate.c:161)
==10789==
==10789== Invalid write of size 1
==10789==    at 0x483B94F: strcat (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10789==    by 0x1097C3: tab_binaire (automate.c:145)
==10789==    by 0x10983F: main (automate.c:161)
==10789==  Address 0x4a54ae8 is 4 bytes after a block of size 4 alloc'd
==10789==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10789==    by 0x109787: tab_binaire (automate.c:140)
==10789==    by 0x10983F: main (automate.c:161)

这是我的 main()...

 int main(int argc, char const argv[]) { 
    char binaire = tab_binaire(12); 
    printf("%s\n", binaire ); 
    liberer_binaire(binaire); 
    return 0; 
    }

【问题讨论】:

  • 贴出的代码无法编译!除此之外,它缺少string.h 和stdlib.h 和stdio.h 所需的#include 语句
  • OT:关于语句:char* res= (char*) malloc(zeroManquant*sizeof(char)); 和char* str = (char*) malloc(sizeof(char)*8); 1) 返回的类型是void*,可以分配给任何指针。强制转换只会使代码混乱,使其更难以理解、调试等。建议删除强制转换。 2)表达式sizeof( char)在标准中定义为1。参数乘以1绝对没有效果。建议删除该表达式。 3) 始终检查 (!=NULL) 返回值以确保操作成功
  • 关于:int main(int argc, char const argv[]) { 由于没有使用任何参数,编译器将输出两条关于未使用参数的警告消息。建议使用签名:int main( void )
  • 在函数中:main() 这个语句:char binaire = tab_binaire(12); 函数:tab_binaire() 返回一个指向 char 的指针,而不是一个 char,所以这个语句不能编译。编译时,始终启用警告,然后修复这些警告。 (对于gcc,至少使用:-Wall -Wextra -Wconversion -pedantic -std=gnu11)注意:其他编译器使用不同的选项来获得相同的结果
  • OT:但是发布的代码只包含不到 30 行;来自 valgrind 的消息指示范围为 140、145、161 的语句。请发布导致问题的实际代码。通常,为您编译的代码发布消息

标签: c memory binary char valgrind


【解决方案1】:

尝试以下调整(您的代码中存在一些问题):

unsigned int_to_int(unsigned k);
char* tab_binaire(int nb);
unsigned int_to_int(unsigned k) {
    if (k == 0) return 0;
    if (k == 1) return 1;                       /* optional */
    return (k % 2) + 10 * int_to_int(k / 2);
}

char* tab_binaire(int nb){
    char* str = (char*) malloc(sizeof(char) * 9);
    sprintf(str, "%d", int_to_int(nb));
    int zeroManquant = 8 - strlen(str);
    char* res= (char*) malloc(9 * sizeof(char));
    int i;
    for (i = 0; i < zeroManquant; i++) {
        res[i]='0';
    }
    res[i] = '\0';
    strcat(res,str);
    free(str);
    str=NULL;
    return res;
}

int main(int argc, char const argv[]) { 
    char *binaire = tab_binaire(12); 
    printf("%s\n", binaire );
    free(binaire);
    //liberer_binaire(binaire); 
    return 0; 
    }

上面的 valgrind 错误意味着您正在尝试访问超出分配区域的内存(read 或 write)变量。

在使用for 循环将'0' 填充到字符串res 的开头之后,您需要将空字符'\0' 放在末尾,以便strcat 从该位置复制第二个字符串。

此时:

char binaire = tab_binaire(12); 

你分配了一个指向 char 的指针,所以你有类型冲突,它只是固定如下:

char *binaire = tab_binaire(12); 

【讨论】:

  • 谢谢,但我不想在 res 中添加结束字符串字符我真的想添加 '0' 字符以将字符串以 8 位的标准化格式放置
  • @TomRibardiere,啊,你之前没有提到过,但是你能试试更新的答案吗,它现在应该可以正常工作了。
  • 是的,现在二进制数的格式很好,但我总是遇到同样的 valgrind 错误
  • 啊,那是来自malloc(zeroManquant*sizeof(char)); 试试改成malloc(9 * sizeof(char));
  • 问题在于strcat 试图写入的内存位置超出了为该进程分配的内存地址。换句话说,除了终止的空字符'\0'之外,您没有为整个字符串分配足够的内存
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-07
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
  • 2013-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多