您好我有以下代码
#include <stdio.h>
#include <conio.h>
typedef struct test
{
int a;
int b;
int c[10];
}tester;
typedef struct done
{
tester* t;
int nn;
}doner;
void main()
{
doner d;
d.t = (tester*)malloc(sizeof(d.t));
d.t->a = 10;
d.t->c[0] = 10;
printf("%d\n", d.t->a);
getch();
return;
}
我认为声明:
d.t = (tester*)malloc(sizeof(d.t));
不正确应该是:
d.t = (tester*)malloc(sizeof(tester));
但是当我运行这段代码时它没有崩溃,请告诉我原因。
答案 0 :(得分:1)
它没有崩溃的事实是因为它有未定义的行为。正确的代码是第二个,但不需要进行强制转换。
d.t = malloc(sizeof(tester));
此外,您需要释放malloc指针。
在许多系统上,写入malloc的缓冲区时不会检查堆,但仅在释放分配的内存时才会检查。在这种情况下,当你释放内存时,你可能会遇到某种崩溃。
答案 1 :(得分:1)
它没有崩溃的事实是这些内存分配错误如此阴险且难以检测的一个重要原因。您的程序只分配一个结构,并且不填充它,因此它超过分配给它的内存量这一事实不会影响其他任何结构。
如果您的程序更多地使用动态分配的内存,那么对malloc
/ free
的调用将触发崩溃,因为您的结构覆盖了堆的链接元数据或程序的其他部分写入自己的malloc数据将覆盖您的结构。无论哪种方式,都不漂亮。
答案 2 :(得分:0)
是的,你是对的。它应该是sizeof(tester)
,因为d.t
只是一个指针。
现在,如果您编写sizeof(d.t)
,则调用Undefined Behavior,这不是崩溃的保证。该程序可能正常运行,运行不正确,崩溃或订购比萨饼。对于具有未定义行为的程序,即使在导致它的构造之前,也无法保证会发生什么。
作为free
内存malloc
- 在这个小样本程序中你不需要担心它,因为系统会在程序退出后释放内存,但一般来说你应尽量释放你分配的任何东西,以避免大型程序中的内存泄漏。
答案 3 :(得分:0)
默认情况下,链接器要求操作系统在启动时为程序分配1MiB(堆栈)内存。您的程序不会崩溃,因为所有引用仍然在操作系统为您的程序保留的相同内存(相同的地址空间)中。从技术上讲,你没有分配那个内存,但由于指针仍然在有效的内存范围内,所以你的程序可以访问它。 这就像在大多数情况下,您可以写入d.t-&gt; c [10](虽然有效索引是0-9) 当使用指针时,会发生崩溃,这些指针对应于分配的内存之外的内存位置。如果您有兴趣,可以通过Google Page Fault 进行详细了解。