我们可以安全地说realloc的结果不会与原始指针混淆吗?

问题描述 投票:4回答:2

说我们有:

char *a = malloc(sizeof(char*));    
char *b = realloc(a,sizeof(char*));

我们能否安全地说b不与a别名? realloc参考页面说明了这一点

原始指针ptr无效,对它的任何访问都是未定义的行为(即使重新分配就位)。

那么我可以将b标记为不混淆a,因为我们不能合法访问a了吗?然而,这可能导致可疑的优化,其中下面的分支将被消除:

if (a == b)
  something..

根据我的理解,a == b本身的比较将是UB,这是技术上正确的优化吗?

c realloc
2个回答
3
投票

解放后,a的值是不确定的。

n1570-§6.2.3(p2):

[...]如果在其生命周期之外引用对象,则行为未定义。当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针的值变得不确定。

如果此不确定值成为陷阱表示,则比较a == b将导致未定义的行为。

请注意,当指针传递给free时,指针指向的对象的生命周期到达其结尾。

进一步阅读: 1. Why isn't a pointer null after calling free? 2. A dangling pointer is indeterminate


2
投票

根据我的理解,a == b本身的比较将是UB ..

嗯,是。

关于“为什么”部分,如haccks's answer中提到的,在指针为free()d之后,它指向的对象到达其生命周期的末尾,从而使指针值不确定。因此,指针本身的任何进一步使用(读取)都将是未指定的行为,并且任何尝试使用它指向的地址都会调用undefined behavior

因此,从技术上讲,您期望的优化是正确的,并且必须使代码表现出已定义的行为,因为代码开始时是不正确的。不要指望编译器纠正你的代码,它可能不会。

那说,关于

我们可以安全地说“b”不是别名“a”吗?

我不清楚你在这里使用别名的理由,但是可以肯定的是,官方的措辞,来自C11,章节§7.22.3.5,

P2:

realloc函数释放ptr指向的旧对象,并返回指向由size指定大小的新对象的指针。新对象的内容应与解除分配之前的旧对象的内容相同,直到新旧大小中的较小者为止。 [...]

P3

[...]如果ptr是空指针,则realloc函数的行为类似于指定mallocsize函数。否则,如果ptr与先前由内存管理函数返回的指针不匹配,或者如果通过调用freerealloc函数释放了空间,则行为未定义。如果无法分配新对象的内存,则不会释放旧对象,并且其值不会更改。

而且,P4:

realloc函数返回指向新对象的指针(可能与指向旧对象的指针具有相同的值),如果无法分配新对象,则返回空指针。

© www.soinside.com 2019 - 2024. All rights reserved.