Malloc 分配超出范围的内存地址

Malloc Allocates Out of Bound Memory Address

我有下面的代码片段,它分配了超出范围的内存:

char *str1 = (char *) malloc(sizeof(char) * BUF_SIZE);
printf ("str1 = ");
scanf("%s", &str1);
int n = strlen(str1);

最初我在 strlen() 中得到一个 Segmentation Fault。在玩过 gdb 之后,我开始知道 str1 位于一个越界的地址。下面显示的是 gdb 输出。

(gdb) print str1
 = 0x636261 <Address 0x636261 out of bounds>

注意:断点设置在调用strlen()的那一行。此外,BUF_SIZE 设置为 #define BUF_SIZE 10

如有任何帮助,我们将不胜感激。谢谢:)

您应该将 str1 而不是 &str1 传递给 scanf()

scanf() 期望 "%s" 格式的 char *;你传递了一个char *的地址。这不会带来幸福。

因为 BUF_SIZE 太小了——你说只有 10——你需要使用:

if (scanf("%9s", str1) != 1)
    …process error or EOF…

这将防止缓冲区溢出。您应该在每次使用 %s 时指定大小(除非您使用 POSIX 修饰符 %msscanf(),但随后规则全部改变)。如果你不这样做,scanf() 可以在你不知道的情况下写出你的字符串变量的范围。

您还应该检查 malloc() 是否成功。总是。每一次。


请注意,使用 GCC 和 -Wall(或 -Wformat)编译会指出您的方法的错误。如果您使用的是 GCC,您应该始终使用 -Wall 进行编译(最好也使用 -Wextra——我使用的选项比这更多)以获得更好的错误报告。

对于包含您的代码的文件,GCC 表示:

warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]

或 'error' 也用 -Werror 编译,我认为这是很好的做法。

我顺便注意到 GDB 告诉我您可能在小端(例如 Intel)机器上输入了 abc 作为字符串。值 0x636261 对应于此。您覆盖了 malloc() 返回的指针,因为您传递了 str1 的地址而不是 str1 中的值——导致内存损坏。

你的代码有几个问题:

  1. 不要通过 指针读取字符串 ,您的意思是 scanf("%s", str1);,删除 &
  2. Don't cast the return value of malloc() in C.
  3. 不要假设分配成功。
  4. 不要为此使用 scanf(),这非常危险,因为您没有向它传递有关可用缓冲区大小的任何信息。最好用fgets().