在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….是的,它会因大的数字而崩溃。感谢所有回答的人。