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

时间:2017-12-26 07:05:25

标签: c realloc

说我们有:

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

我们可以安全地说ba没有别名吗? realloc参考页面说明了

  

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

我可以将b标记为没有别名a,因为我们无法合法访问a吗?然而,这可能导致可疑的优化,其中下面的分支将被消除:

if (a == b)
  something..

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

2 个答案:

答案 0 :(得分:3)

释放后,CREATE FUNCTION dbo.DistinctList ( @List VARCHAR(MAX), @Delim CHAR ) RETURNS VARCHAR(MAX) AS BEGIN DECLARE @ParsedList TABLE ( Item VARCHAR(MAX) ) DECLARE @list1 VARCHAR(MAX), @Pos INT, @rList VARCHAR(MAX) SET @list = LTRIM(RTRIM(@list)) + @Delim SET @pos = CHARINDEX(@delim, @list, 1) WHILE @pos > 0 BEGIN SET @list1 = LTRIM(RTRIM(LEFT(@list, @pos - 1))) IF @list1 <> '' INSERT INTO @ParsedList VALUES (CAST(@list1 AS VARCHAR(MAX))) SET @list = SUBSTRING(@list, @pos+1, LEN(@list)) SET @pos = CHARINDEX(@delim, @list, 1) END SELECT @rlist = COALESCE(@rlist+',','') + item FROM (SELECT DISTINCT Item FROM @ParsedList) t RETURN @rlist END GO 的值是不确定的。

n1570-§6.2.3(p2):

  

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

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

请注意,当指针传递给a == b时,指针指向的对象的生命周期到达终点。

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

答案 1 :(得分:2)

  

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

嗯,是的。

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

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

那说,关于

  

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

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

P2:

  

realloc函数释放ptr指向的旧对象并返回一个   指向具有size指定大小的新对象的指针。新内容   在解除分配之前,对象应与旧对象的对象相同,直到较小的对象   新旧尺寸。 [...]

P3:

  

[...]如果ptr是空指针,则realloc函数的行为类似于malloc函数。   指定size。否则,如果ptr与先前由内存返回的指针不匹配   管理功能,或者如果通过调用free或已释放空间   realloc函数,行为未定义。如果新对象的内存不能   已分配,旧对象未被释放,其值不变。

和,P4:

  

realloc函数返回指向新对象的指针(可能具有相同的指针)   value作为指向旧对象的指针),如果新对象不能,则返回空指针   分配