C++ 访问内存,它不是对象本身的一部分

C++ Access memory which isn't part of the object itself

本文关键字:对象 一部分 访问 内存 C++      更新时间:2023-10-16

我想这听起来很奇怪,但我正在为硬件设备创建一些低级代码。根据具体情况,我需要分配比实际结构所需更多的空间,在那里存储信息,并将对象本身的地址传递给调用者。

当用户正在释放这样一个对象时,我需要在实际释放该对象之前阅读这些信息。

目前,我正在使用简单的指针操作来获取地址(类或额外空间的地址(。然而,我认为,如果我在内部(!(类型的成员函数中进行指针运算,这将更容易理解。处理地址的分配器是唯一知道这种内部类型的分配器。换句话说,返回给用户的类型是不同的。

下面的例子展示了我的意思:

struct foo
{
    int& get_x() { return reinterpret_cast<int*>(this)[-2]; }
    int& get_y() { return reinterpret_cast<int*>(this)[-1]; }
    // actual members of foo
    enum { size = sizeof(int) * 2 };
};

int main()
{
    char* p = new char[sizeof(foo) + foo::size];
    foo* bar = reinterpret_cast<foo*>(p + foo::size);
    bar->get_x() = 1;
    bar->get_y() = 2;
    std::cout << bar->get_x() << ", " << bar->get_y() << std::endl;
    delete p;
    return 0;
}

这样做有争议吗?

这样做似乎不必要地复杂。如果我要实现这样的东西,我会采取一种更简单的方法:

#pragma pack(push, 1)
struct A
{
   int x, y;
};
struct B
{
   int z;
};
#pragma pack(pop)
// allocate space for A and B:
unsigned char* data = new char[sizeof(A) + sizeof(B)];
A* a = reinterpret_cast<A*>(data);
B* b = reinterpret_cast<B*>(a + 1);
a->x = 0;
a->y = 1;
b->z = 2;
// When deallocating:
unsigned char* address = reinterpret_cast<unsigned char*>(a);
delete [] address;

这种实现方式略有不同,但(在我看来(更容易理解,而且不依赖于对存在或不存在的深入了解。如果指针的所有实例都被分配为无符号字符并被删除,那么用户就不需要跟踪块中第一个地址之外的特定内存地址。

非常简单的想法:将您的额外逻辑封装在一个工厂中,该工厂将为您创建对象并以智能的方式删除它们。

您也可以将结构创建为一个更大的对象,并使用工厂函数返回结构的实例,但转换为一个更小的对象,该对象基本上充当对象的句柄。例如:

struct foo_handle {};
struct foo
{
    int a;
    int b;
    int c;
    int d;
    int& get_a() { return a; }
    int& get_b() { return b; }
    //...more member methods
    //static factory functions to create and delete objects
    static  foo_handle* create_obj() { return new foo(); }
    static void delete_obj(foo_handle* obj) { delete reinterpret_cast<foo*>(obj); }
};
void another_function(foo_handle* masked_obj)
{
    foo* ptr = reinterpret_cast<foo*>(masked_obj);
    //... do something with ptr
}
int main()
{
    foo_handle* handle = foo::create_obj();
    another_function(handle);
    foo::delete_obj(handle);
    return 0;
}

现在,您可以在foo结构中隐藏任何可能需要的额外空间,对于工厂函数的用户来说,指针的实际值无关紧要,因为它们主要使用对象的不透明句柄。

您的问题似乎是流行的结构破解的候选问题。

是";structhack";技术上未定义的行为?