【问题标题】:I don't understand why I get this valgrind error我不明白为什么我会收到这个 valgrind 错误
【发布时间】:2016-02-03 08:37:38
【问题描述】:

我得到以下代码:

/* main.c */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main (){
  int i;
  char *msg = "This is a simple and small message";
  int len = strlen (msg);
  char *new_msg = (char *) malloc (len);
  for (i = 0; i < len; i++)
    new_msg[i] = 'A';
  printf ("%s\n", new_msg);
  free (new_msg);
  return 0;
}

我编译了它,然后使用 valgrind 和这个命令运行它:

valgrind --leak-check=full --show-reachable=yes ./main

我得到了这个输出:

==8286== Memcheck, a memory error detector
==8286== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8286== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8286== Command: ./main
==8286== 
==8286== Invalid read of size 1
==8286==    at 0x4C2C1B4: strlen (vg_replace_strmem.c:412)
==8286==    by 0x4EA09FB: puts (ioputs.c:36)
==8286==    by 0x400636: main (main.c:12)
==8286==  Address 0x51de062 is 0 bytes after a block of size 34 alloc'd
==8286==    at 0x4C28C20: malloc (vg_replace_malloc.c:296)
==8286==    by 0x400601: main (main.c:9)
==8286== 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
==8286== 
==8286== HEAP SUMMARY:
==8286==     in use at exit: 0 bytes in 0 blocks
==8286==   total heap usage: 1 allocs, 1 frees, 34 bytes allocated
==8286== 
==8286== All heap blocks were freed -- no leaks are possible
==8286== 
==8286== For counts of detected and suppressed errors, rerun with: -v
==8286== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

我看到所有分配的内存都被释放了,但我仍然得到一个我不明白的错误。

感谢您的帮助。

【问题讨论】:

    标签: c memory valgrind


    【解决方案1】:

    这是一个非常简单的错误:new_msg 的读取无效,因为空终止符不存在。

    您分配的chars 的数量等于原始字符串的长度,因此目前没有空间可以容纳'\0' 而不产生未定义的行为。按如下方式更改代码以解决问题:

    char *new_msg = malloc (len+1);
    for (i = 0; i < len; i++)
        new_msg[i] = 'A';
    new_msg[len] = '\0';
    

    【讨论】:

    • 首先感谢您的解释。现在它起作用了。其次,我看到你删除了 malloc 的演员表。这是为什么?我在有和没有演员的情况下运行它,仍然得到相同的输出(即使在 valgrind 上)。有什么区别吗?
    • @mikmik Here is a good Q&A on casting malloc results。不强制转换的想法是您已经指定了类型,因此您再次重复同一段代码。演员表还可以隐藏细微的错误。
    【解决方案2】:

    您的代码中有许多需要更改的地方。

    1) len 应该是 size_t 而不是 int,因为 strlen() 返回类型为 size_t

    2) (char *) malloc (len); 放弃演员表。这不是错误,尽管有一些不应该施放的原因。

    3) new_msg 不是以 NULL 结尾的 \0。这就是发生错误的原因。

    【讨论】:

    • 数字 1 和 2 不是此问题的原因。提及它们是可以的,但请明确区分。
    • @Haris 演员表不是错误,但一方面是非常有用的信息,并且可以防止不正确的分配。另一方面
    【解决方案3】:

    您使用strlen() 获取长度,但不包含“\0”。
    所以当你malloc一个新数组时,你应该使用len + 1,并且设置new_msg[len]'\0'

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多