通过预定义的静态地址访问寄存器在 C++ 中是未定义的行为吗?

2023-12-25

我正在编译一个 C++ 程序以在独立环境中运行,并且我正在运行的 CPU 定义了一个可用的 32 位外设寄存器(编辑:内存映射) at PERIPH_ADDRESS(正确对齐,并且不与任何其他 C++ 对象、堆栈等重叠)。

我编译以下代码PERIPH_ADDRESS预定义,稍后将其与完整程序链接并运行它。

#include <cstdint>

struct Peripheral {
    const volatile uint32_t REG;
};

static Peripheral* const p = reinterpret_cast<Peripheral*>(PERIPH_ADDRESS);

uint32_t get_value_1() {
    return p->REG;
}

static Peripheral& q = *reinterpret_cast<Peripheral*>(PERIPH_ADDRESS);

uint32_t get_value_2() {
    return q.REG;
}

extern Peripheral r;
// the address of r is set in the linking step to PERIPH_ADDRESS

uint32_t get_value_3() {
    return r.REG;
}

是否有任何get_value函数(直接或通过p/q)有未定义的行为?如果是的话,我可以修复它吗?

我认为一个等效的问题是:任何符合标准的编译器都可以拒绝为我编译预期的程序吗?例如,一台已打开 UB 消毒器的设备。

我看过[基本.stc.动态.安全 http://eel.is/c++draft/basic.stc.dynamic.safety] and [basic.compound#def:object_pointer_type http://eel.is/c++draft/basic.compound#def:object_pointer_type] 但这似乎只限制了指向动态对象的指针的有效性。我认为它不适用于这段代码,因为“对象”位于PERIPH_ADDRESS从未被假定为动态的。我想我可以有把握地说,由p永远不会到达其存储期限的末尾,可以考虑static.

我也看过为什么 C++ 不允许从有效地址和类型创建有效指针? https://stackoverflow.com/questions/53200002/why-does-c-disallow-the-creation-of-valid-pointers-from-a-valid-address-and-ty以及对该问题的回答。它们也只引用动态对象的地址及其有效性,因此它们不回答我的问题。

我考虑过但无法回答自己的其他问题可能有助于解决主要问题:

  • 我是否会遇到任何 UB 问题,因为该对象从未在 C++ 抽象机中构造过?
  • 或者我实际上可以认为该对象是一个具有正确“构造”的静态存储持续时间的对象吗?

显然,我更喜欢引用任何最新 C++ 标准的答案。


指针强制转换的含义是由实现定义的[expr.reinterpret.cast] https://timsong-cpp.github.io/cppwp/expr.reinterpret.cast#5.sentence-2

整型或枚举类型的值可以显式转换为指针。转换为足够大小的整数(如果实现中存在这样的整数)并返回到相同指针类型的指针将具有其原始值;指针和整数之间的映射是由实现定义的。

Therefore this is well-defined. If your implementation promises you the result of the cast is valid, you are fine.

链接的问题是关于指针算术的,这与当前的问题无关。

† By definition, a valid pointer https://timsong-cpp.github.io/cppwp/basic.compound#3 points to an object, implying subsequent indirections are also well-defined. Care should be exercised in making sure the object is within its lifetime https://timsong-cpp.github.io/cppwp/basic.life#7.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过预定义的静态地址访问寄存器在 C++ 中是未定义的行为吗? 的相关文章

随机推荐