2017-06-03 67 views
3

我想知道为什么我不得不使用malloc来动态创建内存,而我已经有了指针可以自由操纵内存。 所以我创造了这个代码,但是这个代码腐败,称‘被破坏“为什么我不能使用指针而不是malloc

有人能解释为什么这代码失败,那周围的变量栈’?

#include <stdio.h> 

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

这是未定义的行为。 – BLUEPIXY

+0

虽然技术上*未定义的行为*,但最可能的是您正在写入不属于您的堆栈内存。这可能表现为另一个本地变量或函数参数获取更改的值。或者你因为函数的返回地址被破坏 - 或者更糟 - 当函数返回时在指令指针的其他位置结束而崩溃。 – selbie

+0

你需要更多的基本概念研究。你的头衔反映了根本的误解。使用'malloc'进行堆分配预留存储空间供程序使用。您的程序可以使用指针算术来读取和写入已经保留的存储中的值。得到一本好书。 – Gene

回答

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以获取所需的内存。然后你可以自由地读取和写入该块。

5

你不知道在&a + 1上可能存储的实现是什么。这可能是维持操作环境完整性所需的关键信息。尽管不知道它可能用于什么,但您可以修改它。所以什么都可能发生。

不要写入不属于你的内存!

0

您使用int * arr1 = &a;来请求指向a的指针。系统分配arr1。所以该方法可以安全地请求一个指针。

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

0

您已将变量a的地址指定为指针arr1。 ARR1由4所声明整数指针ARR1 + 1级的增量地址(的sizeof(int)的),即,如果ARR1是0x00000003 ARR1 + 1是0x00000007

*(arr1 + 1) = 2; 

变得无效其超出分配用于,写入无效存储器内存使你的程序崩溃

相关问题