Tag: undefined behavior

通过严格解释C标准允许对可能无效的指针进行操作

原始问题 (请参阅“编辑:更新的方案”) 这个问题可能是一个或另一个方面的重复,涉及到超出范围的对象的指针的未定义行为的大量问题。但我在这里找到的所有问题主要是专门的用例。 所以我想把这个问题颠倒过来,不要问是否禁止某些事情,但是究竟允许什么? 有一个可能的场景:你有一个带有指针的函数 – 你不知道它是否来自一个(仍然)有效的对象。 在所有情况下哪些操作不是未定义的行为? 哪个可能有未指定的副作用? int * myFunc(const int * const A, int * B) { … } 编辑:更新的方案 在对问题的评论和Matt McNabbs的回答中 ,有人指出UB最有可能上升,因为在调用场景中的函数期间使用了无效指针(s值)。 因此,我会稍微改变一下场景(按照Keith Thompsons回答的例子): int *ptr = malloc(sizeof *ptr); /* the value of ptr is now valid, possibly NULL */ if (ptr != NULL) { /* the value of ptr is […]

Objective-C中的空指针取消引用是否为未定义的行为?

在C和C ++中,空指针取消引用是未定义的行为。 Objective-C怎么样? 换句话说,这个代码保证做什么? *(long*)0 = 0; 背景:我想知道这个答案是否可能触发未定义的行为,可能导致随机的事情,如声明被优化或甚至更奇怪的东西。 当然,我不认可这样做。 但是,了解语言规则也很重要。

使用char未定义的行为访问数组元素?

由于不清楚什么是未定义的行为以及什么不在C中,我想知道使用char访问数组元素是否是未定义的行为。 例如: char c = ‘A’; int a[3000]; printf(“%i\n”, a[c]); 我知道实际上字符和整数在某种程度上是可以互换的,但我仍然不确定。

当`if(变量%2 == 0)`时程序崩溃

我正在写一个找到完美数字的程序。 读完这些完美的数字之后,我遇到了一个列表: 完美数字列表 。 目前的输出是: 28 // perfect 496 // perfect 8128 // perfect 130816 // not perfect 2096128 // not perfect 33550336 // perfect 我决定创建数组并使用数字,将数字全部除以(不包括其余数字)。 因此,通过添加数组的所有元素,我将能够validation它是否是一个完美的数字。 但应用程序崩溃,我无法理解为什么: #include #include int main() { unsigned long number; unsigned long arr2[100] = {0}; int k = 0; for ( number = 0; number <= 130816; number++ ) […]

将结构指针转换为联合指针

我有一个包含各种兼容struct成员的union : enum Type { T1, T2, … }; struct S1 { enum Type type; … }; struct S2 { enum Type type; … }; … union U { enum Type type; struct S1 as_s1; struct S2 as_s2; … }; 这些结构的type字段被视为不可变,并且只访问与当前type对应的union的字段。 我知道只要type不变量得到维护,就会定义将union U *为struct S1 * ,但反过来也是如此吗? struct S1 *s1 = malloc (sizeof (struct S1)); […]

未定义的行为和序列点

什么是“序列点”? 未定义的行为和序列点之间的关系是什么? 我经常使用像a[++i] = i;这样有趣而复杂的表达a[++i] = i; ,让自己感觉更好。 我为什么要停止使用它们? 如果您已阅读此内容,请务必访问后续问题重新加载未定义的行为和序列点 。 (注意:这是Stack Overflow的C ++常见问题解答的一个条目。如果你想批评在这种forms下提供常见问题解答的想法,那么发布所有这些的meta上的post就是这样做的地方。这个问题在C ++聊天室中受到监控,其中FAQ的想法首先出现在那里,所以你的答案很可能被那些提出想法的人阅读。)

C函数指针类型兼容性

编写一个与函数回调一起工作的库,我经常对具有相同调用约定和相同签名的类型进行类型化(和调用)函数指针,但有一个例外:它们具有指向不同类型(所有数据)的参数,或无效指针。 最近,我发现它可能不那么安全,根据这个: https : //stackoverflow.com/a/14044244/3079266 基本上,正如我所理解的那样,如果参数的类型是兼容的,那意味着函数指针类型也是兼容的,并且应该没有问题。 现在,我有3个问题。 第一:这是否意味着,由于指向不同类型的指针在技术上是不兼容的,我所做的可能导致未定义的行为? 第二:在哪里(在什么样的架构上)我可以逃脱它? 其中是Windows x86还是x64版本? 第三:我哪里可以逃脱它?

如果函数永远不会返回,则省略return语句是有效的

考虑一个可能永远不会退出的函数foo() : int foo(int n) { if(n != 0) return n; else for(;;); /* intentional infinite loop */ return 0; /* (*) */ } 省略最终的回报声明是否有效? 如果我遗漏最后的陈述,它会引起不确定的行为吗?

读取不确定的值会调用UB吗?

SO上的各种受尊敬的高代表用户坚持认为阅读具有不确定值的变量“总是UB”。 那么在C标准中究竟提到了哪一个呢? 很明显,不确定的值可能是未指定的值或陷阱表示: 3.19.2 不确定的价值 要么是未指定的值,要么是陷阱表示 3.19.3 未指明的价值 本国际标准对在任何情况下选择的值没有要求的相关类型的有效值 注意未指定的值不能是陷阱表示。 3.19.4 陷阱表示 一个对象表示,不需要表示对象类型的值 很明显,读取陷阱表示会调用未定义的行为,6.2.6.1: 某些对象表示不需要表示对象类型的值。 如果对象的存储值具有这样的表示,并且由不具有字符类型的左值表达式读取,则行为是未定义的。 如果这样的表示是由副作用产生的,该副作用通过不具有字符类型的左值表达式修改对象的全部或任何部分,则行为是未定义的.50)这种表示称为陷阱表示。 但是,不确定值不一定包含陷阱表示。 实际上,对于使用二进制补码的系统,陷阱表示非常罕见。 在C标准中,它实际上是说读取不确定的值会调用未定义的行为吗? 我正在阅读C11的非规范性附件J,并发现这确实列为UB的一个案例: 具有自动存储持续时间的对象的值在不确定时使用(6.2.4,6.7.9,6.8)。 但是,列出的部分无关紧要。 6.2.4仅规定有关生命时间和变量值变得不确定的规则。 类似地,6.7.9是关于初始化的,并说明变量的值如何变得不确定。 6.8似乎大多无关紧要。 这些部分都没有包含任何规范性文本,说访问不确定的值可能导致UB。 这是附件J中的缺陷吗? 然而,在关于左值的6.3.2.1中有一些相关的规范性文本: 如果左值指定了一个自动存储持续时间的对象,该对象可以使用寄存器存储类声明(从未使用其地址),并且该对象未初始化(未使用初始化程序声明,并且在使用之前未对其进行任何赋值) ),行为未定义。 但这是一种特殊情况,它仅适用于从未使用过地址的自动存储持续时间的变量。 我一直认为6.3.2.1的这一部分是UB关于不确定值(不是陷阱表示)的唯一情况。 但是人们一直坚持认为“它总是UB”。 那么究竟提到了哪里?

数组指针算法 – 合法和未定义的行为

我问自己这些代码行是否会在C和C ++中产生未定义的行为。 我试着回答每一点,阅读标准关于数组下标的内容(C 6.5.6 – 8)。 我没有发布整个段落,因为它很长。 此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向一个超过数组对象的最后一个元素,如果表达式Q指向一个超过数组对象的最后一个元素,表达式(Q)-1指向数组对象的最后一个元素。 如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义。 如果结果指向一个超过array> object的最后一个元素的结果,则它不应该用作被计算的一元*运算符的操作数。 1 int a[10]; 2 int b = a[9]; // ok 3 int c = a[10]; // UB 4 int* d = (a + 10); // ok 5 int* e = &a[10]; // ok from C99 (& and [] are ignored, pointer is not […]