繁体   English   中英

我的malloc函数分配的次数超出了我的预期

[英]Is my malloc function allocating more than I intend to

这是我正在尝试运行的代码。 malloc函数分配800个字节。

void DynamicMemoryAllocationUsingMalloc()
{
    int* p,i;
    if((p = (int*) malloc(800)) == NULL)
    {
        printf("\n Out of Memory \n");
        exit(0);
    }

    for(i =0;i < 800;i++)
    {
        printf(" 0x%x", (p + i));
        printf(" %d\n", *(p + i));

    }
}

但是在我打印地址的for循环中,我能够安全地跳过800个内存位置(使用整数指针p ),每个4字节长(整数的大小),相当于3200字节。 这是怎么可能的,或者我很幸运没有得到访问冲突错误,即使我实际上进入了我尚未分配给我的程序的内存区域? 我看到垃圾写在所有内存位置的原因显而易见,因为我没有将这些内存位置设置为任何内容。

注意 :它是在Windows 7上运行的C程序。

这是怎么可能的,或者我很幸运没有得到访问冲突错误,即使我实际上进入了我尚未分配给我的程序的内存区域?

代码到达printf(" %d\\n", *(p + 200)); 是试图读取外部分配的内存。 这是未定义的行为 UB。

UB是UB。 它可能每天都会发生,或者在下次运行时更改。


你不幸运。 幸运的是你的代码会在那里停止。

即使读取未初始化的int数据也是UB。 因此,只要printf(" %d\\n", *(p + 0));代码就有UB(或者可能是实现定义printf(" %d\\n", *(p + 0)); IAC,代码可以在那里停止。


我的malloc函数分配的次数超过了我的意图吗?

这是棘手的一点。 调用UB的代码会产生可疑的结果。 没有UB的代码没有标准的方法来测试问题。 确定这一点的唯一非UB方式是库是否提供了具有答案的函数。

printf("True size %lu\n", (unsigned long) True_size(p));

注意:OP断言int是4个字节。

它的工作原因可能是因为您没有超出当前为该进程分配的内存范围。 现代系统通常将内存分配给4千字节的进程。 您的第一次分配可能在页面的开头,而您正在窥探的内存可能位于该第一页的未分配的剩余部分中。

操作系统无法检测到无效的内存访问,除非它们超出为您的进程分配的内存范围。 就操作系统而言,它为您的流程提供了页面和流程正在使用它。 它不关心你的进程使用的malloc例程是否说你的程序“拥有”那个内存。

在获得访问冲突之前,查看您可以阅读的内容可能是一个有趣的实验。 在尝试阅读之前,只需循环并打印每个地址。

但是在我打印地址的for循环中,我能够安全地跳过800个内存位置(使用整数指针p),每个4字节长(整数的大小),相当于3200字节。

我猜“安全”你的意思是程序不会崩溃。 当应用于航空旅行时,这是一个正确的定义,但不适合计算机程序。

这是怎么可能的,或者我很幸运没有得到访问冲突错误,即使我实际上进入了我尚未分配给我的程序的内存区域?

通过访问未分配的内存,您的程序会显示未定义的行为。 认识到这个问题,你会受到赞扬。 但是,引用@KerrekSB,“未定义的行为是未定义的”。 一般来说,您不能假设未定义行为的任​​何特定表现。

例如,如果您的程序碰巧崩溃,并且存在访问冲突,那么您可以确定它已经展示了未定义的行为,因为C没有定义任何产生该行为的方法。 但仅仅因为它似乎做了你所期望的并不意味着它的行为是定义的。 如果没有定义,那么一般来说,你也不能确信它是否一致。

所以基本上,是的,你很幸运。 或者也许不走运。 我自己,我宁愿让程序崩溃,以便我收到警报。

这是一个未定义行为的例子。 从逻辑上讲,这个程序应该打破。 但它并不是因为过程映像有一些额外的空间,你可以在没有操作系统发送段错误的情况下溢出。 我的意思是,不是去800,而是上升到1000,10000,等等。 最终,您将在任意数量的迭代中获得段错误。

你可以这么高的原因是因为你的程序在ram中有很多开销,这个开销被允许溢出。

C标准答案 :访问超出已分配内存的内存会导致未定义的行为。

现实世界的答案 :您的程序使用malloc()分配内存,malloc()从操作系统(在本例中为Windows)中提供内存。 但是,每次malloc()调用都不会导致对操作系统的调用。 实际上,Malloc通常会分配比现在需要的内存更多的内存,然后将中断至少是您请求的大小的块。 这是出于性能原因而完成的,因为每次调用操作系统都会产生一些开销。 此外,还有一个最小“页面大小”,它是可以从操作系统分配的最小内存单元。 4096字节是典型的页面大小。

因此,在您的情况下,您正在访问malloc已从系统配置但尚未分配使用的内存。 您应该避免这种情况,因为下一次调用malloc可能会导致内存被分配用于其他目的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM