6

我正在尝试使用 malloc 动态创建一个大小为 2 的数组。这是我的代码:

int *d = (int*)malloc(2 * sizeof(int));
d[0] = 4;
d[1] = 5;
d[2] = 8;
d[3] = 9;
d[4] = 7;
int i;

for (i = 0; i < 5; i++)
   printf("%d \n", d[i]);

当我运行此代码时,它会打印4, 5, 8, 9, 7.

我想知道它如何能够分配比我要求的更多的内存(5 个整数)(2 个整数)?

4

6 回答 6

9

我想知道它如何能够分配比我要求的更多的内存。

它没有。您正在调用未定义的行为。一种可能的结果*是您的程序似乎“工作”。


*可以说,最糟糕的。

于 2013-07-09T02:19:08.687 回答
3

除了建议的内容之外,如果我可以添加一些额外的注释。

不确定你在什么操作系统上运行它,但如果你在 Linux 上,你不确定某些东西是否应该工作或不通过valgrind. 在我的例子中,它编译了一份关于你的代码所有错误的很好的报告(包括不释放malloc-ed 内存)。

Invalid write of size 4你对内存的三个额外写入我得到了三个。它还通知我你在循环中读取的无效内存,Invalid read of size 4最后它给了我一些关于你的代码泄漏的统计信息:

HEAP SUMMARY:
    in use at exit: 8 bytes in 1 blocks
  total heap usage: 1 allocs, 0 frees, 8 bytes allocated

LEAK SUMMARY:
   definitely lost: 8 bytes in 1 blocks

最后,不要强制转换 malloc 的结果。

于 2013-07-09T02:37:34.093 回答
3

就像奥利说的那样,它是undefined。它可能有效,也可能无效。但现实情况是,即使它可能在 99% 的时间里工作,它至少会失败一次,并且你会SEGFAULT从读取或写入你的进程不应该使用的内存中得到一个,而你'最终也会导致几乎无法调试的内存泄漏。

于 2013-07-09T02:21:48.340 回答
1

这似乎工作的原因是因为您正在增加指针以指向内存中的新点(您的程序可能会或可能不会分配使用)。我猜你是在堆栈上声明这个,这就是为什么你的未定义行为看起来是“好的”。

我认为您不了解指针的功能和您使用的语法。注意以下是等价的:

int arr[ 2 ] = { 1, 2 };
int *pi = &arr;

// The following output is equivalent to...
for ( int i = 0; i < 2; i++ ) {
  printf( "arr[i] = %d.\n", arr[ i ] );
}

// this.
for ( int i = 0; i < 2; i++ ) {
  printf( "*(p + i) = %d.\n", *( p + i ) );
}

考虑一下这个代码的替代实现,以强调如何通过索引数组外部的元素来指向新的内存地址。

int *d = ( int * )malloc( 2 * sizeof( int ) );

*( d + 0 ) = 4; // Observe you are accessing the memory location d points to.
*( d + 1 ) = 5; // Observe you are accessing the memory location d + 4 bytes (or 8 if 64-bit) points to...
*( d + 2 ) = 8; // ...
*( d + 3 ) = 9; // ...
*( d + 4 ) = 7; // Observe you are assigning a value to the memory location of d + 24 bytes (or 48 bytes if 64-bit).

for ( int i = 0; i < 5; i++) {
   printf( "%d \n", *( d + i ) );
}

只是对您的代码的快速说明。malloc 通常应该跟在一个 free 之后——所以适当地使用它,这样就不会出现内存泄漏。

我希望这有帮助!如果我犯了错误,请随时纠正我。

于 2013-07-09T03:59:00.283 回答
1

C 不做边界检查。您正在踩踏您的程序不拥有的内存。

于 2013-07-09T02:24:08.410 回答
1

当您调用未定义的行为时,您永远不知道会发生什么。例如,当我运行程序时,我得到以下输出:

4、5、8、51、1629501832

于 2013-07-09T02:36:38.470 回答