【发布时间】:2015-07-09 16:28:07
【问题描述】:
原始问题
(请参阅“编辑:更新的场景”)
这个问题可能以一种或另一种方式与大量关于超出范围的对象的指针的未定义行为等问题重复。但我在这里找到的关于这个主题的所有问题大多是专门的用例。所以我想把这个问题颠倒过来,不是问是否禁止某事,而是问究竟什么是允许的?
有一个可能的场景:你有一个函数,它需要一个指针——你不知道它是否来自一个(仍然)有效的对象。哪些操作在所有情况下都不是未定义的行为?哪些可能有未指定的附带条件?
int * myFunc(const int * const A, int * B)
{
...
}
编辑:更新的场景
在问题的 cmets 和 Matt McNabbs answer 中指出,无论如何,UB 很可能已经上升,因为在场景中调用函数期间使用了无效的指针(s 值)。因此,我将稍微改变一下场景(按照Keith Thompsons answer 的示例):
int *ptr = malloc(sizeof *ptr);
/* the value of ptr is now valid, possibly NULL */
if (ptr != NULL)
{
/* the value of ptr is valid and non-null */
free(ptr);
/* the value of ptr is now invalid */
... /* here operations in question */
}
允许的操作列表:
(由您的答案和 cmets 完成和纠正。)
- 定义明确:取指针变量的大小。例如。
sizeof(ptr) - 定义明确:取解引用指针的大小(假设它不是
void *)。例如。sizeof(*ptr)(参见 EOF 和 Jonathan Leffler 的 cmets)。 - 定义明确:将另一个(有效)值分配给指针(而不是引用的变量!)。例如。
ptr = NULL; -
定义明确:访问指针的表示(来自Keith Thompson 的answer 的示例):
unsigned char rep[sizeof ptr]; memcpy(rep, &ptr, sizeof ptr); /* ok, accesses the representation */ /* but not the value */
没有按照标准定义好的操作:
(由您的答案和 cmets 完成和纠正。)
这些操作通常被视为在无效指针上定义良好,但根据标准没有定义良好:
- 未定义:比较指针的值(甚至与 NULL 指针常量)
- 未定义:转换为整数值
与所有未定义的行为一样,您可能会在许多机器上(ab)使用指针而侥幸,但 C 标准不保证您会侥幸逃脱,并且存在(或曾经是)这样滥用指针会导致程序严重失败。
有关一般规则,请参阅Keith Thompson's answer — 以及下面的大量 cmets。
【问题讨论】:
-
我,可能还有 Mark A,很想知道人们为什么投反对票。这对我来说似乎是一个很好的问题......
-
没有投反对票,但这个问题的前提是错误的(来自 C Rationale):“不管如何创建无效指针,任何使用它都会产生未定义的行为。即使分配,与空指针常量比较,或与自身比较,在某些系统上可能会导致异常。"
-
@Jashaszun 这个问题太宽泛了。
-
所以...你说的是没有允许的操作...这很苛刻。谢谢你提供的信息。
-
@Jashaszun 这个问题怎么可能同时变得广泛并导致“什么都不允许”? :-)
标签: c pointers undefined-behavior c89