我有以下代码,我希望它会失败,但似乎工作正常。我很困惑为什么这不会造成某种分段错误。
#include <stdio.h>
#include <stdlib.h>
struct entry {
int foo;
};
struct table {
int size;
struct entry* entries;
};
typedef struct table *Table;
typedef struct entry Entry;
int main() {
Table table = malloc(sizeof(struct table));
table->entries = malloc(sizeof(struct entry) * 1);
(table->entries)[5].foo = 5;
for (int i = 0; i < 10; i++) {
printf("Entry #%d: %d\n",i,(table->entries)[i].foo);
}
}
我原本预料到,因为我只为table-&gt;条目中的一个条目分配了足够的空间,所以访问0以外的任何索引都将超出范围。但是当我运行这个程序时,它打印出5作为索引5处条目的foo值,其余为0,这是正确的行为。为什么这不会失败?
答案 0 :(得分:2)
其他人会说它更好,但未定义的行为未定义。
没有定义。它可能会奏效。它可能不会。
这一切都取决于那些内存位置。
你写了一个不好的位置。你读了其他一些。你碰巧没碰到任何东西 太重要了。
你在malloc'ed区域写了一个字。也许你做了更多的计算 因为你写入了malloc的数据结构会导致麻烦。也许不是。
答案 1 :(得分:1)
你 访问越界,但这只是调用'未定义的行为'。当您调用“未定义的行为”时,可能会发生任何事情。一种可能性是程序崩溃;另一个是该程序没有崩溃,似乎没问题。要么是可能的;它有时甚至可能会崩溃,有时甚至不会崩溃。
如果您尝试了更多的内存分配,或尝试释放内存,那么您更有可能看到问题已经出错。然而,即便这样也无法保证;您可能错过了所有敏感信息(malloc()
等使用的字节来确定分配了哪个内存,哪些不是。)
你可以写:
table->entries[i].foo
你不需要在(table->entries)[i].foo
附近使用括号,尽管它们是无害的,除非他们建议新手正在编码。
答案 2 :(得分:0)
它没有失败,因为尽管你正在写入未分配的内存,但这个内存完全在合法的HEAP空间内。但是你没有向内存管理器声明你正在使用那个内存空间,未来malloc()
可能会尝试分配到同一个区域,你会得到重叠的缓冲区和未定义的行为。
答案 3 :(得分:0)
这是未定义的行为,您正在访问的内存位置不是“您的”。你在内存中写了一些没有被你分配的东西,破坏了那个内存位置。
答案 4 :(得分:0)
#include <stdio.h>
#include <stdlib.h>
struct entry {
int foo;
};
struct table {
int size;
struct entry* entries;
};
typedef struct table *Table;
typedef struct entry Entry;
int main() {
Table table =(table)malloc(sizeof(struct table));
table->entries =(entry*)malloc(sizeof(struct entry) * 10);
(table->entries)[5].foo = 5;
for (int i = 0; i < 10; i++) {
printf("Entry #%d: %d\n",i,(table->entries)[i].foo);
}
}
首先,您需要将(void *)类型转换为使用malloc
时所需的指针类型。其次,你只分配条目指针,这意味着,当你使用(table-&gt;条目)[5] .foo时,你可能会访问内存非法,所以这是一个危险的行为。最后,您需要在打印之前初始化foo
。你需要遵守规则,不要写那样的代码。