在malloc()之后写入超出范围的指针不会导致错误
当我尝试下面的代码时,效果很好。我错过什么了吗在malloc()之后写入超出范围的指针不会导致错误,c,malloc,memory-corruption,C,Malloc,Memory Corruption,当我尝试下面的代码时,效果很好。我错过什么了吗 main() { int *p; p=malloc(sizeof(int)); printf("size of p=%d\n",sizeof(p)); p[500]=999999; printf("p[0]=%d",p[500]); return 0; } 我用malloc(0*sizeof(int))或任何东西尝试过,但效果很好。只有当我根本不使用malloc时,程序才会崩溃。因此,即使我为数组p
main()
{
int *p;
p=malloc(sizeof(int));
printf("size of p=%d\n",sizeof(p));
p[500]=999999;
printf("p[0]=%d",p[500]);
return 0;
}
我用malloc(0*sizeof(int))或任何东西尝试过,但效果很好。只有当我根本不使用malloc时,程序才会崩溃。因此,即使我为数组p分配0内存,它仍然正确地存储值。那我为什么还要和马洛克在一起呢 如果不分配内存,则p中有垃圾,因此写入它可能会失败。一旦进行了有效的malloc调用,p将指向有效的内存位置,您可以对其进行写入。您正在覆盖不应该写入的内存,但没有人会握住您的手告诉您。如果运行程序和内存调试器(如valgrind),它会告诉您。 欢迎来到C.它看起来工作正常,但一点也不安全。通过在分配的内存块之外写入数据,您正在覆盖一些不应该覆盖的数据。这是SEGFULTS和其他内存错误的最大原因之一,您在这个简短的程序中观察到它似乎起了作用,这使得查找根本原因变得如此困难 阅读,特别是关于内存损坏的部分,开始理解问题 是分析内存错误(如您提供的错误)的极好工具 @大卫评论得很好。比较两次跑步的结果。请注意,后者会导致ideone.com上的运行时错误(几乎没有有用的输出!)(单击链接),而前者会根据您的经验成功
int main(void)
{
int *p;
p=malloc(sizeof(int));
printf("size of p=%d\n",sizeof(p));
p[500]=999999;
printf("p[0]=%d",p[500]);
p[500000]=42;
printf("p[0]=%d",p[500000]);
return 0;
}
写到你记忆的尽头是一种未定义的行为™, 这意味着任何事情都有可能发生——包括你的程序运行,就好像你刚才所做的是完全合法的一样。你的程序运行的原因就像你做了malloc(501*sizeof(int))一样,完全是特定于实现的,并且确实可以特定于任何东西,包括月亮的相位。这是因为无论你使用malloc()时使用什么大小,p都会被分配一些地址。虽然,如果大小为零,您将引用无效内存,因为内存尚未分配,但它可能位于不会导致程序崩溃的位置内,尽管行为未定义 现在,如果不使用malloc(),它将指向一个垃圾位置,并试图访问可能导致程序崩溃的位置 我用malloc(0*sizeof(int))试过了 根据C99,如果传递给
malloc
的大小为0,则C运行时可以返回空指针,或者分配行为与请求为非零分配一样,但返回的指针不应被取消引用。因此,它是由实现定义的(例如,某些实现返回零长度缓冲区),在您的情况下,您不会返回空指针,但您使用的是不应该使用的指针。如果您在其他运行时尝试,您可能会返回空指针 调用malloc()时,会从较大的页面中为您分割出一小块内存
malloc(sizeof(int));
实际上不在32位计算机上分配4个字节(分配器将其填充到最小大小)+用于跟踪区块整个生命周期的堆元数据大小(区块根据其大小放置在容器中,并由分配器标记为“使用中”或“可用”)。hxxp://en.wikipedia.org/wiki/Malloc 或者更具体地说hxxp://en.wikipedia.org/wiki/Malloc#dlmalloc_and_its_derivatives 如果你在Linux上测试这个
因此,在你的区块范围之外写作并不一定意味着你会崩溃。在p+5000时,您没有在为该初始块分配的页面边界之外进行写入,因此从技术上讲,您是在向有效的映射地址进行写入。欢迎来到内存损坏。
我们的工具可以检测到此错误。它知道p的分配是分配给一个4字节的块,因此进行了分配,它位于分配p的区域之外。它会告诉您p[500]赋值是错误的。尝试用一个非常大的数字替换500….是的,它会因大的数字而崩溃。感谢所有回答的人。