【问题标题】:Can I cast a memory area with a class type?我可以使用类类型投射内存区域吗?
【发布时间】:2021-12-31 05:44:16
【问题描述】:
class RW {
    int a;
public:
    int read() const {
        return this->a;
    }
    void write(int _a) {
        this->a = _a;
    }
};

#define PHYSICAL_ADDRESS (0x60000000)
#define SIZEOF_PHY_ADDR  (sizeof(RW))
// assume physical memory area is already assigned for the sizeof(RW)

void main()
{
    int val;
    void *phy_ptr = PHYSICAL_ADDRESS;
    RW *rw_ptr = (RW *)phy_ptr;

    rw_ptr->write(1);
    val = rw_ptr->read();
}

请假设上面的代码是伪代码。 我有一个可读取/可写的共享物理内存区域。我想将该区域的指针转换为读写。我可以这样做吗?可以接受吗?

我已经检查过它工作正常,但我不确定它是否是正确的 cpp 方式。

感谢任何回复和讨论! 提前致谢!

【问题讨论】:

  • 您可以而且应该使用展示位置new
  • 您不应该在 C++ 代码中使用“C”样式转换,但请观看有关“reinterpret_cast”的内容:您可能想观看此“C++ Weekly - Ep 185 - Stop Using reinterpret_cast!” :youtube.com/watch?v=L06nbZXD2D0。 TLDR:您很容易遇到未定义的行为。
  • 需要初始化内存吗?您的类成员结构是否简单(标准布局),如显示的代码中所示?对于这种访问,有一些解决方案可能现在可以工作,也有一些解决方案绝对符合标准并定义了行为。我假设您要的是后者。
  • @Sebastian 我没有初始化内存。还有更多数据,但基本上它只是从共享内存中读取和写入成员变量。那么,如果可以的话,您能说出解决方案的名称或给我一个提示吗?
  • 为了使这种操作在 C++ 中定义行为 open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0593r6.html 被采用到 C++20。非常实用的 std::start_lifetime_as 仅适用于 C++23。在此之前,您可以将放置 new 与对象类型 与 std::byte 一起使用: new (start) std::byte[length];基本类型 char、unsigned char 和 byte 在内存区域中隐式创建(类)类型。

标签: c++


【解决方案1】:

您不需要强制转换:您可以使用placement new 运算符在该地址创建对象。

void main()
{
    int val;
    void *phy_ptr = PHYSICAL_ADDRESS;
    //RW *rw_ptr = (RW *)phy_ptr;
    RW *rw_ptr = new(phy_ptr) RW;

    rw_ptr->write(1);
    val = rw_ptr->read();

    rw_ptr->~RW();
}

【讨论】:

  • 在这种情况下我是否也应该在最后删除 rw_ptr ?你能解释一下为什么我不应该投吗?
  • 因为如果你只使用 cast,new 将不会被调用并且你不会有你的类的有效实例。
  • @PepijnKramer 好的,感谢您的回复,我将研究实例以及当内存大小已经与类相同时它需要什么额外的东西。顺便说一句,在这种情况下,调用 delete 会让我中止。所以我应该只使用新而不删除。
  • 最后我几乎从不使用这种技术,除非我完全控制了内存布局。生成共享内存布局的代码是否使用不同的编译器和/或编译器设置编译?如果是这样,您可能需要实现正确的序列化 (isocpp.org/wiki/faq/serialization)
  • 没有展示位置删除操作符。您手动分配内存并显式提供指针,因此您无需使用 delete 释放此内存。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多