在C语言中在数组末尾之外写入

在C语言中在数组末尾之外写入,c,arrays,pointer-arithmetic,C,Arrays,Pointer Arithmetic,我最近发现C允许我执行以下操作: char* myArray[1]; myArray[0] = malloc(1024 * sizeof(char)); strcpy(myArray[0], "Hello"); myArray[1] = malloc(1024 * sizeof(char)); strcpy(myArray[1], "World"); //repeat ad absurdum 有效地允许我填充myArray任意多个指向数据的指针,尽管最初只显式地为一个指针请求内存 为什么

我最近发现C允许我执行以下操作:

char* myArray[1];

myArray[0] = malloc(1024 * sizeof(char));
strcpy(myArray[0], "Hello");

myArray[1] = malloc(1024 * sizeof(char));
strcpy(myArray[1], "World");

//repeat ad absurdum
有效地允许我填充
myArray
任意多个指向数据的指针,尽管最初只显式地为一个指针请求内存

为什么允许这样做? 这是一种良好的做法,还是会导致不可预见的后果?
据我所知,一个数组的不同索引在内存中是相邻分配的,由于初始化数组时从未明确请求过
myArray[1]
的地址,因此它可能被其他数据占用

C是一种非常不安全的语言。你通常可以做任何你想做的事,而且你所做的肯定会毁掉你的记忆。通常在简单的程序中,你不会注意到效果,但它很快就会变得明显

简言之,这是允许的,但很危险,不应该这样做


在用c编程时,您必须在每一行检查自己。

c不会对数组访问进行边界检查,试图读取或写入数组末尾会导致未定义的行为。缓冲区溢出是一种常见的恶意软件攻击。

长期以来,人们一直说,C语言可以让你射中自己的脚。我既不知道也不在乎你是不是一个负责任的枪支拥有者。基本上,边界检查需要时间。没有时间做其他事情。对停车收费表进行编程时,这并不重要。在编写游戏、sim卡或宇宙飞船时,这些奢侈的时间是无法负担的。这就是为什么在编写C语言时,你应该利用你能找到的所有编译器警告、静态分析器和动态检查工具。(ASAN、valgrind、splint等)不幸的是,因为这里的
myArray
似乎是一个堆栈变量,valgrind不会捕获错误访问,因为您实际上只是破坏堆栈上的下一个变量。-fsanize=address(clang和gcc)可能有助于调试内存错误引起的错误。此外,像valgrind这样的工具也有帮助。但正如Jonathon所说,外部工具不可能捕捉堆栈处理错误。+1表示缓冲区溢出。但我认为你应该详细说明一下,让OP知道他们有多讨厌。