我正在尝试使用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个整数)?
答案 0 :(得分:9)
我想知道它是如何能够分配比我要求的更多的内存。
它没有。您正在调用未定义的行为。一个可能的结果 * 是您的计划似乎&#34;工作&#34;。
<小时/> *可以说是最差的。
答案 1 :(得分:3)
就像奥利所说,它是未定义。它可能有效,但可能没有。但实际情况是,即使它可能在99%的时间内起作用,它至少会失败一次,并且你会从读取或写入内存得到SEGFAULT
,而你的过程不应该是使用,你最终会得到几乎无法调试的内存泄漏。
答案 2 :(得分:2)
除了我可以添加一些额外注释之外的建议。
不确定您在运行此操作系统的操作系统,但如果您在Linux上,则无论何时您不确定某些内容是否有效,都可以通过valgrind
运行。在我的例子中,它编译了一个关于代码中所有错误的好报告(包括没有释放malloc
- 内存)。
我为你对内存做的三次额外写入有三个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
答案 3 :(得分:1)
C不进行边界检查。你正在踩着你的程序不拥有的内存。
答案 4 :(得分:1)
当您调用未定义的行为时,您永远不知道会发生什么。例如,当我运行程序时,我得到以下作为输出:
4,5,8,51,1629501832
答案 5 :(得分:1)
这似乎起作用的原因是因为您正在递增指针以指向内存中的新位置(您的程序可能会或可能不会被分配使用)。我猜你在堆栈上声明这个,这就是为什么你的未定义行为似乎是“ok”。
我认为您不了解指针的功能和您使用的语法。注意以下内容是等效的:
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 - 所以要适当使用它,这样就不会有内存泄漏。
我希望这有帮助!如果我犯了错误,请随意纠正我。