为什么我不能使用指针添加而不是malloc

时间:2017-06-03 02:32:27

标签: c pointers malloc

我想知道为什么我必须使用malloc来动态创建记忆, 虽然我已经有指针添加自由操纵的记忆。 所以我创建了这段代码,但是这段代码腐败了,说'围绕变量'a'的堆栈已经损坏了'

有人可以解释为什么这段代码失败了吗?

#include <stdio.h>

int main(void)
{
    int a = 1;
    int * arr1 = &a;
    *(arr1 + 1) = 2;
    printf("%d %d\n", *arr1, *(arr1+1));
}

4 个答案:

答案 0 :(得分:5)

您不知道实施可能存储在&a + 1的内容。它可能是维持操作环境健全性所需的关键信息。尽管不知道它可能用于什么,你可以修改它。所以任何事情都可能发生。

请勿写入不属于您的内存!

答案 1 :(得分:4)

只是因为你可以对某个任意地址执行指针运算并不意味着你应该这样做。 C给你很大的灵活性来做你想做的事情,但这也意味着它相信你做正确的事情,你不是。

您尝试执行的操作是写入超过sizeof(int)地址的内存地址a字节。该内存地址不是a的一部分,写入它会调用undefined behavior

至于您的特定情况,在大多数托管实现中,局部变量通常存储在堆栈中。因此,如果您写过变量的边界,您很可能会覆盖相邻变量或函数的返回地址。鉴于您的程序崩溃,您可能正在执行后者。

以下是覆盖其他变量的说明:

#include <stdio.h>

int main(void)
{
    int before = 0;
    int a = 1;
    int after = 0;
    int * arr1 = &a;
    *(arr1 + 1) = 2;
    printf("%d %d\n", *arr1, *(arr1+1));
    printf("before=%d, after=%d\n", before, after);
}

在这个例子中,我拿了你的例子并在a之前和之后添加了一个变量。当我运行它时,我得到以下输出:

1 2
before=2, after=0

您可以看到before现在设置为2,即使它没有明确设置。这意味着它出现在a之后的堆栈中。因此,通过写一个过去的a,您最终会写入before

重申一下,这是未定义的行为。编译器可以按任何顺序在堆栈上排列变量。如果您要添加额外的printf调用或使用不同的优化设置进行编译,则可能会得到不同的结果。我用-O1重新编译了上面的代码并运行它导致了核心转储。

因此,如果需要特定数量的内存并且没有为其明确预留空间,则需要调用malloc来获取所需的内存。然后你可以自由地读写这个块。

答案 2 :(得分:0)

使用int * arr1 = &a;请求指向a的指针。 arr1由系统分配。因此,该方法可以安全地请求指针。

对于另一种情况,请使用*(arr1 + 1) = 2请求指针(arr1 + 1)指向整数值。您可能不知道其他程序或其他用途是否部署(arr1 + 1)。这不是一个安全的内存地址。这就是程序被破坏的原因。

答案 3 :(得分:0)

您已将变量a的地址指定给指针arr1。 arr1被声明为整数指针arr1 + 1以4为增量地址(sizeof(int)),即如果arr1为0x00000003,则arr1 + 1为0x00000007

*(arr1 + 1) = 2;

因为超出内存分配给a,写入无效内存导致程序崩溃而变得无效