说我们有:
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,这是技术上正确的优化吗?
答案 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作为指向旧对象的指针),如果新对象不能,则返回空指针 分配