在C中使用一个数组

时间:2013-10-01 01:57:42

标签: c arrays malloc

我有以下代码,我希望它会失败,但似乎工作正常。我很困惑为什么这不会造成某种分段错误。

#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,这是正确的行为。为什么这不会失败?

5 个答案:

答案 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。你需要遵守规则,不要写那样的代码。