【问题标题】:Malloc Allocates Out of Bound Memory AddressMalloc 分配越界内存地址
【发布时间】:2015-01-27 15:11:23
【问题描述】:

我有以下 sn-p 代码,它分配内存超出范围:

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
$1 = 0x636261 <Address 0x636261 out of bounds>

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

任何帮助将不胜感激。谢谢:)

【问题讨论】:

  • 在“读取”之前添加memset(str,0,BUFSIZE)
  • 不要使用scanf,而是使用fscanffgets
  • @Algo:为什么?我自己通常建议不要使用*scanf(),但在这种情况下,这几乎不是问题,特别是如果建议使用fscanf(),它与scanf() 有相同的问题...?

标签: c string segmentation-fault malloc scanf


【解决方案1】:

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

scanf() 期望 char * 用于 "%s" 格式;你传递了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=]

或者在使用-Werror 编译时也会出现“错误”,我认为这是一种很好的做法。

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

【讨论】:

    【解决方案2】:

    您的代码中有几个问题:

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

    【讨论】:

    • 第三点的意思是我应该验证从 malloc 返回的指针不是 NULL 吗?关于第一点,这是我的错。调试器对此无能为力:)
    • 很高兴知道第二点,它会自动提升 void *。
    • @sidkamaria 是的,你应该先检查返回的指针不是NULL,然后再假设它不是。
    猜你喜欢
    • 2016-11-14
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多