2015-02-24 69 views
0

试图分配一个由N个元素组成的char数组。动态字符数组

#include <stdio.h> 
#include <malloc.h> 

int main() 
{ 
    int N = 2; 

    char *array = malloc(N * sizeof(char)); 

    array[0] = 'a'; 
    array[1] = 'b'; 
    array[2] = 'c'; // why can i do that?? 

    printf("%c", array[0]); 
    printf("%c", array[1]); 
    printf("%c", array[2]); //shouldn't I get a seg fault here?? 

    return 0; 
} 

的问题是:

由于我分配2 * 1 = 2个字节的存储器,这意味着,我可以在我的阵列2个字符。我怎么可能有更多?我还打印sizeof(*数组),它打印8个字节。我在这里错过了什么?

+4

这是*未定义的行为*。高兴你的猫没有着火。 – Zeta 2015-02-24 18:33:19

+3

如果你经过数组的末尾(这是未定义的行为),C并不在乎。只要这个内存存在,它就会有*机会*,这取决于你的编译器,操作系统和其他东西。然而,你的编译器应该给你一个警告。 – Jon 2015-02-24 18:34:27

+2

'sizeof(* array)'应该是1,而不是8.也许你打印了'sizeof(array)',它给出了一个指针的大小。 – interjay 2015-02-24 18:34:40

回答

2

当程序尝试访问未被操作系统映射到其虚拟内存地址空间的内存地址时,会发生分段错误。

内存分配发生在页面中(通常是4k或8k,但你也可以得到更大的页面)。所以malloc()调用从操作系统获取一个内存页面,并为它分割出一部分,并返回一个指向它的指针。在这种特定情况下,数组之后仍有大部分页面(未分配,但已用于后续对malloc())的调用 - array [2]引用页面内的有效地址,因此不存在分段错误。

但是,您正在访问超出数组范围的内存,如注释中所述,这是未定义的行为,可能会通过覆盖无关变量的值而导致较大程序中的内存损坏。

+0

实际上......在大多数平台上(无论如何32位或64位),精确的示例显示不会导致任何重要的损坏。几乎所有的'malloc'实现都为指针分配至少*足够的空间。这就是说,它仍然是不确定的行为,是一种可怕的做法。 – 2015-02-24 18:53:12

+0

哈哈 - 好点:) – isedev 2015-02-24 18:53:55

+0

所以这个工程,因为我正在访问的内存存在,但它不是数组的“部分”。 – pirox22 2015-02-24 18:56:13

0

第0个和第1个元素位于有效内存分配内部。用第二个元素,你已经侵入未分配的内存。将工作正常,直到内存的一部分被分配给其他东西,然后你的第2个元素将开始有疯狂的价值观。你的代码会变得疯狂。但正如@jon指出的,编译器应该能够捕捉到这一点,除非你已经要求它关闭它。

+0

我使用的是gcc,它不打印任何警告:/ – pirox22 2015-02-24 19:32:16

+0

我错误地确信gcc本身应该能够捕捉到这一点,但没有它没有。试过夹板。除了这个边界检查外,它还捕获了其他问题。奇怪。 – 2015-02-24 20:09:27