malloc(0) 返回什么?[重复]

2024-10-14 08:40:00
admin
原创
73
摘要:问题描述:返回什么malloc(0)?答案是否相同realloc(malloc(0),0)?#include<stdio.h> #include<malloc.h> int main() { printf("%p ",...

问题描述:

返回什么malloc(0)

答案是否相同realloc(malloc(0),0)

#include<stdio.h>
#include<malloc.h>
int main()
{
        printf("%p
", malloc(0));
        printf("%p
", realloc(malloc(0), 0));
        return 0;
}

Linux GCC 的输出:

manav@manav-workstation:~$ gcc -Wall mal.c
manav@manav-workstation:~$ ./a.out
0x9363008
(nil)
manav@manav-workstation:~$

每次输出都会发生变化malloc(0)。这是标准答案吗?除了学术研究之外,为什么有人会对获得这样的指针感兴趣?

编辑:

如果malloc(0)返回虚拟指针,那么以下工作如何进行:

int main()
{
    void *ptr = malloc(0);
    printf("%p
", realloc(ptr, 1024));
    return 0;
}

编辑:

以下代码每次迭代都会输出“可能”。为什么它不会失败?

#include<stdio.h>
#include<malloc.h>
int main()
{

        int i;
        void *ptr;
        printf("Testing using BRUTE FORCE
");
        for (i=0; i<65000; i++)
        {
                ptr = malloc(0);
                if (ptr == realloc(ptr, 1024))
                        printf("Iteration %d: possible
", i);
                else
                {
                        printf("Failed for iteration %d
", i);
                        break;
                }
        }
        return 0;
}

解决方案 1:

其他人已经回答了如何malloc(0)工作。我将回答您提出的尚未回答的一个问题(我认为)。问题是关于realloc(malloc(0), 0)

返回什么malloc(0)?答案是否相同realloc(malloc(0),0)

标准是这样说的realloc(ptr, size)

  • 如果ptrNULL,它的行为就像malloc(size)

  • 否则(ptr不是NULL),它会释放指向的旧对象指针ptr并返回指向新分配缓冲区的指针。但如果size是 0,C89 表示效果相当于free(ptr)。有趣的是,我在 C99 草案(n1256 或 n1336)中找不到该语句。在 C89 中,在这种情况下返回的唯一合理值是NULL

因此,有两种情况:

  • malloc(0)返回NULL实现。那么您的realloc()调用相当于realloc(NULL, 0)。这相当于malloc(0)上面的(在本例中是NULL)。

  • malloc(0)返回非NULL。那么,调用 相当于free(malloc(0))。在这种情况下,malloc(0)realloc(malloc(0), 0)等价

请注意,这里有一个有趣的情况:在第二种情况下,当成功时malloc(0)返回非 时NULL,它仍可能返回NULL以指示失败。这将导致类似这样的调用:realloc(NULL, 0),这相当于malloc(0),它可能返回 ,也可能不返回NULL

我不确定 C99 中的遗漏是否是疏忽,或者这是否意味着在 C99 中,realloc(ptr, 0)NULL ptr不等同于free(ptr)。我刚刚用 尝试过gcc -std=c99,上面的内容等同于free(ptr)

编辑:我想我明白你的困惑是什么:

让我们看一下示例代码中的一段:

ptr = malloc(0);
if (ptr == realloc(ptr, 1024))

上面的代码与 不同malloc(0) == realloc(malloc(0), 1024)。在第二个代码中,malloc()调用了两次,而在第一个代码中,你将一个先前分配的指针传递给realloc()

让我们首先分析一下第一个代码。假设成功时malloc(0)不返回,则具有有效值。当您执行时,基本上会为您提供一个大小为 1024 的新缓冲区,并且变为无效。符合要求的实现可能会返回与中已有的地址相同的地址。因此,您的条件可能会返回 true。(但请注意,查看after的值可能是未定义的行为。)NULL`ptrrealloc(ptr, 1024)realloc()ptrptrifptr`realloc(ptr, 1024)

现在你要问的问题是:malloc(0) == realloc(malloc(0), 1024)。在这种情况下,我们假设malloc(0)LHS 和 RHS 上的 都返回非NULL。那么,它们肯定是不同的。此外,malloc()LHS 上的 返回值尚未被free()d,因此任何其他malloc()calloc()或 都realloc()可能不会返回该值。这意味着如果你将条件写为:

if (malloc(0) == realloc(malloc(0), 1024)
    puts("possible");

您不会possible在输出中看到(除非malloc()和都realloc()失败并返回NULL)。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    void *p1;
    void *p2;

    p1 = malloc(0);
    p2 = realloc(p1, 1024);
    if (p1 == p2)
        puts("possible, OK");

    /* Ignore the memory leaks */
    if (malloc(0) == realloc(malloc(0), 1024))
        puts("shouldn't happen, something is wrong");
    return 0;
}

在 OS X 上,运行我的代码时没有输出任何内容。在 Linux 上,它会打印possible, OK

解决方案 2:

malloc(0)就 C99 而言是实现定义的。

来自C99 [第 7.20.3 节]

通过连续调用 calloc、malloc 和 realloc 函数分配的存储的顺序和连续性 未指定。如果分配成功,则返回适当对齐的指针,以便可以将其分配给指向任意类型对象的指针,然后用于访问分配空间中的此类对象或此类对象数组(直到明确释放空间)。分配对象的生命周期从分配一直延续到释放。每次这样的分配都会产生一个指向与任何其他对象不相交的对象的指针。返回的指针指向分配空间的起始(最低字节地址)。如果无法分配空间,则返回一个空指针。 如果请求的空间大小为零,则行为是实现定义的:要么返回一个空指针,要么行为就像大小是某个非零值,只是返回的指针不能用于访问对象。

解决方案 3:

在 C89 中,malloc(0) 依赖于实现 - 我不知道 C99 是否已修复此问题。在 C++ 中,使用:

char * p = new char[0];

定义良好 - 您获得一个有效、非空的指针。当然,您不能使用该指针访问其指向的内容,否则会引发未定义的行为。

至于为什么存在这种情况,它对于某些算法来说很方便,并且意味着您不需要在代码中塞满对零值的测试。

解决方案 4:

C99 标准

如果无法分配空间,则返回空指针。如果请求的空间大小为零,则行为由实现定义:要么返回空指针,要么行为就像大小是某个非零值一样,只是返回的指针不得用于访问对象。

解决方案 5:

comp.lang.c常见问题解答如下:

ANSI/ISO 标准规定它可以执行上述任一操作;行为由实现定义(参见问题 11.33)。可移植代码必须注意不要调用 malloc(0),或者为可能返回 null 做好准备。

因此,最好避免使用malloc(0)

解决方案 6:

在您的第一个程序中,还没有人愿意谈论的一点是,realloc长度 0 与 是相同的free

来自 Solaris 手册页:

realloc()函数将 指向的块的大小更改为ptr字节size,并返回指向(可能已移动)块的指针。内容将保持不变,直到新旧大小中较小者。如果ptrNULL,则对于指定的大小,realloc()
其行为类似。如果 为
且 不是空指针,则指向的空间可供应用程序进一步分配,但不会返回给系统。只有在应用程序终止时,内存才会返回给系统。malloc()`size0ptr`

如果人们不知道,这可能会成为一个不好的惊喜的根源(就发生在我身上)。

解决方案 7:

参见 C99,第 7.20.3 节:

如果请求的空间大小为零,则行为由实现定义:要么返回一个空指针,要么行为就好像大小是某个非零值,但返回的指针不能用于访问对象。

calloc()这对于所有三个分配函数(即、malloc()和)都有效realloc()

解决方案 8:

我认为这取决于情况。我检查了 Visual Studio 2005 源代码,并在 _heap_alloc 函数中看到了这一点:

if (size == 0)
    size = 1;

我认为在很多情况下,你可能想要一个有效的指针,即使请求零字节。这是因为这种一致的行为使检查指针变得更容易,因为:如果你有一个非 NULL 指针,那就没问题;如果你有一个 NULL 指针,那么你可能有问题。这就是为什么我认为大多数实现都会返回一个有效的指针,即使请求零字节。

解决方案 9:

如果 malloc(0) 返回虚拟指针,那么以下工作如何进行:

void *ptr = malloc(0);

`printf("%p

", realloc(ptr, 1024));`

我不知道您说的“虚拟指针”是什么意思。如果malloc(0)返回非 NULL,则为ptr指向大小为零的内存块的有效指针。malloc实现以特定于实现的方式保存此信息。 realloc知道(特定于实现的)找出指向ptr大小为零的内存块的方法。

(如何malloc做到reallocfree一点取决于具体实现。一种可能性是分配比请求的多 4 个字节,并将大小存储在内存块之前。在这种情况下,((int *)ptr)[-1]将给出内存块大小,即0。您永远不应该在代码中这样做,它仅供realloc和使用free)。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用