我知道我应该使用realloc来生成一个数组,但是在一瞬间的想法中,我就这样做了。我意识到这种方法是错误的,因为我在不分配数组的情况下通过增加它来破坏堆。所以我基本上写垃圾。但是当代码很小而没有其他事情发生时,我不明白为什么这不应该起作用。我为前几个值得到垃圾
#include <stdio.h>
#include <stdlib.h>
int main()
{
int **p = NULL;
int i=0;
int size = 5;
int *n = NULL;
p = malloc(sizeof(int*));
printf("p = %p \n", p);
for( i=0; i < size; i++ )
{
int *k;
k = malloc(sizeof(int));
*k = i;
p[i] = k;
printf("%p, %p, val = %d \n", k, p[i], *k);
}
printf("Now print the array -- \n");
for( i=0; i < size; i++ )
{
int *k;
k = p[i];
printf("value at mem %p == %d \n", p[i], *k);
}
printf("now print the next values in p \n");
for( i=0; i < size; i++ )
{
printf("value at %p = %p \n", p+i, *(p+i) );
}
return 0;
}
以下是代码的输出 -
p = 0x7f8ffbc031c0
0x7f8ffbc031d0, 0x7f8ffbc031d0, val = 0
0x7f8ffbc031e0, 0x7f8ffbc031e0, val = 1
0x7f8ffbc031f0, 0x7f8ffbc031f0, val = 2
0x7f8ffbc03200, 0x7f8ffbc03200, val = 3
0x7f8ffbc03210, 0x7f8ffbc03210, val = 4
Now print the array --
value at mem 0x7f8ffbc031d0 == -71290384
value at mem 0x7f8ffbc031e0 == -71290352
value at mem 0x7f8ffbc031f0 == 2
value at mem 0x7f8ffbc03200 == 3
value at mem 0x7f8ffbc03210 == 4
now print the next values in p
value at 0x7f8ffbc031c0 = 0x7f8ffbc031d0
value at 0x7f8ffbc031c8 = 0x7f8ffbc031e0
value at 0x7f8ffbc031d0 = 0x7f8ffbc031f0
value at 0x7f8ffbc031d8 = 0x7f8ffbc03200
value at 0x7f8ffbc031e0 = 0x7f8ffbc03210
我无法解释为什么前两个值都是垃圾,即使p和p + 1指向的内存地址是我放在那里的。
答案 0 :(得分:1)
声明
p = malloc(sizeof(int*));
仅将单个元素分配给p
; p[1]
到p[4]
不存在(或者更恰当地说,您不拥有与这些元素相对应的内存)。要分配size
- int *
元素数组,该行必须为
p = malloc( size * sizeof *p ); // sizeof *p == sizeof (int *)
另外,
int *k;
k = malloc(sizeof(int));
*k = i;
p[i] = k;
可以简单地写成
p[i] = malloc( sizeof *p[i] ); // sizeof *p[i] == sizeof (int)
if ( p[i] ) // **always** check the result of a malloc, calloc, or realloc call!
*p[i] = i;
答案 1 :(得分:0)
你的代码错了。您将p
声明为指针的单个指针,但随后将其用作size
项的数组。为此,您必须分配所需大小的数组。您当前的p = malloc(sizeof(int*))
只分配一个指针,正确的代码为p = (int**)malloc(size * sizeof(int*))
。
我在Visual Studio中测试了你的代码,我在p [0]和p [1]中看不到任何垃圾。我假设它基于您的编译器和/或操作系统如何组织堆。由于您未在问题中指定它们,因此很难发表评论。
因此,您不会将p[1]
的内存分配给p[4]
。但是你在那里写价值。那么你认为这些价值实际上去了哪里?这些值写入RAM,但它不是p []数组拥有的内存。这两个奇怪的数字-71290384和-71290352实际上是您写给p[2]
和p[4]
的值。 (它分别是ff8ffbc031f0十六进制和ff8ffbc03210十六进制,高位设置但不相关。)这是因为当您写入p[2]
时,实际上写入为其他本地k
分配的内存。此行为取决于具体的堆组织,因此它在其他操作系统和/或编译器上有所不同。
此外,虽然p [2]和p [4]被意外写入分配给其他变量的内存中,但似乎通过写入未分配的p [1]和p [3]来破坏堆。
答案 2 :(得分:0)
该程序具有未定义的行为。不过我可以解释这个程序运行的结果。
通常当内存分配请求小于段落的大小(通常等于16个字节)时,函数malloc
会分配一个与段落大小完全相等的内存块。
在此声明之后
p = malloc(sizeof(int*));
在地址
分配了16个字节p = 0x7f8ffbc031c0
因此你可以使用地址
0x7f8ffbc031c0
和0x7f8ffbc031c8
属于已分配的范围。
语句
在循环中分配的第一个和第二个块k = malloc(sizeof(int));
是
0x7f8ffbc031d0
0x7f8ffbc031e0
由于语句
而在同一循环中 p[i] = k;
存在超出指针p
指向的分配范围的内存。
所以你必须按顺序使用表达式p[i]
0x7f8ffbc031c0 - p[0]
0x7f8ffbc031c8 - p[1]
0x7f8ffbc031d0 - p[2] - Oops! the address 0x7f8ffbc031d0 is overwritten
0x7f8ffbc031d8 - p[3]
0x7f8ffbc031e0 - p[4] - Oops! the address 0x7f8ffbc031e0 is overwritten!
因此,存储前两个整数的前两个地址将被覆盖。