undefined-behavior 相关问题

编译或执行打破语言规则的程序的不可预测的结果,编译器,解释器和运行时系统都不得强制执行。

基类有时可以初始化派生类的成员吗?

SO是一场狗屎秀。感谢您的搭车。

回答 1 投票 0

在联合体中使用 std::string 和 int

在同一联合内使用 std::string (或其他非平凡类型)与 int (或其他平凡和非平凡类型)是否正确? 我已经这样实现了: #包括 在同一联合内使用 std::string(或其他非平凡类型)与 int(或其他平凡和非平凡类型)是否正确? 我已经这样实现了: #include <iostream> #include <string> struct Foo { enum Type {data_string, data_int}; int m_type; Foo(Type t) : m_type(t) { if (t == Type::data_string) { new (&s) std::string(); } } ~Foo() { if (m_type == Type::data_string) { s.~basic_string(); } } union { int n; std::string s; }; }; int main() { Foo f1(Foo::Type::data_string); f1.s = "hello "; std::cout << f1.s; Foo f2(Foo::Type::data_int); f2.n = 100; std::cout << f2.n; } 而且效果非常好。但我不确定这段代码。从 C++ 标准角度来看,它是正确的代码吗? 您不应该将 union 与非平凡类型一起使用。 联合并不意味着处理其中 C++ 对象的正确构造和析构。 您在代码中手动处理了它,这在技术上是正确的,但很容易出错。如果你在联盟中建造或破坏了错误的类型,你很容易进入UB土地。 一般来说,在 C++ 中,建议使用 std::variant 作为通用求和类型。 因此,我建议使用以下内容代替您的工会: std::variant<int, std::string> m_value; 这样你的 Foo 构造函数和析构函数就可以被 default 编辑。该变体将负责 std::string(或其中任何其他重要类型)的正确构造和销毁。

回答 1 投票 0

如何处理“引用打包字段未对齐”错误?

我正在重新访问旧代码,现在遇到一个错误(合成重新创建): 错误[E0793]:对打包字段的引用未对齐 --> src/main.rs:9:22 | 9 | println!("{:?}",

回答 1 投票 0

是否定义了非数组组成成员之间字节指针偏移量的计算?

我理解 expr.add#4.2 背后的推理,将 + 和 - 限制为针对同一数组元素的指针,这在我关于偏移点的问题的几条评论中进行了解释...

回答 1 投票 0

这些指针转换中的未定义行为是什么? [重复]

我正在设计一个非常小的偏移指针类。它显示优化级别相关的输出,表明未定义的行为。但为什么会这样,又该如何解决呢?参见示例 #包括 我正在设计一个非常小的偏移指针类。它显示优化级别相关的输出,表明未定义的行为。但为什么会这样,又该如何解决呢?参见示例 #include <cstddef> #include <iostream> template<typename T> class NullableOffsetPtr { public: NullableOffsetPtr(T const* ptr) : offset_{ ptr == nullptr ? std::ptrdiff_t{1} : reinterpret_cast<std::byte const*>(ptr) - reinterpret_cast<std::byte const*>(this)} { } T* get() { return offset_ == 1 ? nullptr : reinterpret_cast<T*>(reinterpret_cast<std::byte*>(this) + offset_); } private: std::ptrdiff_t offset_; // Using units of bytes, as alignments of *this and *ptr may not match. }; class Sample { }; int main(int argc, char* argv[]) { Sample sample; NullableOffsetPtr<Sample> ptr{&sample}; std::cout << "(ptr.get() == &sample): " << (ptr.get() == &sample) << std::endl; std::cout << "ptr.get(): " << ptr.get() << std::endl; std::cout << "&sample : " << &sample << std::endl; return 0; } 使用所有优化级别 -O1 及以上,gcc 编译的可执行文件的输出为 (ptr.get() == &sample): 0 ptr.get(): 0x7ffe503cd42f &sample : 0x7ffe503cd42f 尽管各个值(每次运行都不同)显示为相同,但指针比较的结果为 false! 当然,reinterpret_cast立即敲响了UB的铃声,但根据我的理解,应该在reinterpret_cast中的类型别名的范围内。 以下修改将“修复”此行为,但不是令人满意的解决方案,并且不能解释上面的问题: 禁用优化 使用 clang++ 另请参阅 godbolt 示例 如果两个对象都是同一顶级对象的子对象(可能是间接的),则只能使用指针算术从另一个对象访问一个对象。 (例如,如果您将两个对象设置为同一类实例的非静态数据成员,GCC 就会开始运行。) 相关措辞如下: [expr.add]/4.2 表示 + 只能用于在同一数组的元素之间移动指针。同样,-只能减去同一数组元素之间的指针。 [basic.types.general]/4 表示您可以将对象视为 unsigned char 的数组。 [basic.lval]/11.3祝福char、unsigned char和std::byte,允许通过指针/引用访问任何对象,忽略严格的别名。 大家普遍认为,你不能在uintptr_t中进行指针运算来解决[expr.add]/4.2,但我现在找不到相关的措辞。 关于生命周期和别名的措辞总体来说是一团糟,如果你挖掘得太深,很多事情在技术上都是 UB (或暗示如此),而在实践中却没有得到执行。例如,有一个可以通过指针访问字节的概念。它用在 std::launder 的描述中,据我所知,没有在其他地方使用过(该标准实际上并没有在任何地方说访问“无法访问”的字节实际上是 UB)。 Sample 是一个空类,由于这在您的代码中没有明显的影响,因此它可以与 NullableOffsetPtr 共享一个地址。 因此,打印时 &sample 和 ptr.get() 可以提供相同的输出。 但是,NullableOffsetPtr的构造函数中的指针减法是未定义的行为: 当两个指针表达式 P 和 Q 相减时,结果的类型是实现定义的有符号整型;该类型应与标头中定义为 std::ptrdiff_t 的类型相同([support.types.layout])。 如果 P 和 Q 的计算结果均为空指针值,则结果为 0。 否则,如果 P 和 Q 分别指向同一数组对象 x 的数组元素 i 和 j,则表达式 P - Q 的值为 i−j。 否则,行为未定义。 [expr.add] p5

回答 2 投票 0

调用 FD_ISSET 时未定义的行为

我有一个带有 Heisenbug 的程序,我正在尝试诊断。结合使用 gdb 和 Ghidra,我已经能够追踪到特定部分的崩溃。这是我的代码的要点: FD_Z...

回答 1 投票 0

指针的有效性如何与未初始化的指针值交互?

我已经看到,在 C 或 C++ 抽象机中,仅在内存中形成指向无效点的点的行为就是未定义的行为。 例如 int* arr = 新 int[10]; int* 最后 = arr + 9; // ...

回答 1 投票 0

C99 和 MISRA C:2012 中指针转换的未定义行为

我正在开发一个 C99 项目,该项目要求我们遵循 MISRA C:2012 标准。 规则 11.3 本质上是防止在不声明合理的情况下在不同对象类型之间转换指针

回答 1 投票 0

打印未初始化的变量时会发生什么?

我检查过自己,我写了一个这样的程序 int main() { 整数我; 计算<< i; return 0; } I ran the program a few times and the result was same all the time, zero. I've tried it in C an...

回答 4 投票 0

如果没有成员活跃,您可以覆盖工会的内存吗?

以下程序负责摆桌子、吃饭和清理桌子。吃饭前和吃饭后,盘子所在的地方都会被清理干净。根据 C++23 标准允许这样做吗?还是未定义

回答 1 投票 0

下面的代码是有效的C吗? (空指针的指针算术)

我最近在阅读C标准ISO/IEC 9899:2018规范。其中,第6.5.6节(加法运算符)描述了对+运算符的约束。规则[8]说: 当一个表达式...

回答 1 投票 0

将 unique_ptr 传递给完成处理程序时,Boost ASIO“错误地址”错误

我正在尝试使用 ASIO 实现一个简单的 TCP 服务器。这里的主要区别是我使用 std::unique_ptr 来保存缓冲区而不是原始指针,并且我将它们移动到完整的内部...

回答 1 投票 0

calloc() 的错误实现引入了除零以及如何通过测试检测它?

我有一个作业,其中我必须编写自己的 calloc 函数(以及其他一些 Libc 函数),唯一允许的内置函数是 malloc() 和 free()。 对于上下文:...的分级...

回答 1 投票 0

装配中的数据竞争危险吗?

我知道 C 中的数据竞争是未定义的行为。 但数据竞争是硬件级别的问题吗? 如果我要在汇编中编写一个程序,其中一个线程写入某个广告......

回答 1 投票 0

在方程中传递 char* 而不是 char[] 时,函数中会出现分段错误。如何访问 char* 文字? (避免只读)

功能代码如下: 无效 TrimRight(char* s) { if(!*s) 返回; 字符*结束= 0; for(char c; c = *s; s++) { if(c == ' ') { if(end == 0) end = s; } 否则结束=0; ...

回答 1 投票 0

__builtin_clz 使用非 0 的有效输入返回错误答案

因此,在我的 M1 MacBook 上,我正在编写一个库(使用 Apple Clang),为此我需要计算某些数字的前导(和尾随,但这似乎工作得很好)零的数量。 我显然

回答 1 投票 0

使用 asm 读取“无出处”的指针被认为是安全的?

我最近写了这个相当简单的asm函数 #[内联(总是)] pub fn usize_raw_load_acquire(dst: &mut usize, src: *const usize) { 使用 std::arch::asm; debug_assert!(src.is_aligned(...

回答 1 投票 0

为什么将联合成员指针强制转换为联合指针而不是 UB,因为它们可以具有不同的大小?

在下面的代码片段中,发生了缓冲区溢出,即在执行 u->b = *b; 时。 A类{ 民众: 整数x; A() { x = 5; } }; B类{ 民众: 整数x; 浮动y; B() { x =...

回答 1 投票 0

非常量对象的const字段可以被const_cast-ed吗?

众所周知,UB从真正的常量中删除常量 常量 int i = 0; const_cast(i) = 42; // UB 但是,当您处理对非 co 的 const 引用时,这样做是完全可以的...

回答 1 投票 0

联合的未定义行为

在使用 3D 点时,我遇到了这种类型定义方法: 并点_3d { 结构体{ GL双x、y、z; } 坐标; GL双选项卡[3]; }; 因此,坐标...

回答 1 投票 0

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