c++对象的动态地址重定位
visual Dynamic address relocation of C++ objects
我想知道是否有可能使用动态基址而不是静态基址来处理类。基本思路如下:
对象A的定义如下:
class A
{
//member variables
...
//non-virtual member functions
...
//virtual methods
virtual void foo(...);
...
};
这个类不能实例化为堆栈对象,并且没有标准的new操作符。
相反,对象有一个location new,它将基址和基址的偏移量放入内存,并使用它来计算用于构造的绝对地址。
我想做的是让对象在代码中被访问,如下所示:
A* clsA=new(base,offset) A();
...
clsA->foo( ... );
,
(char*)clsA == (char*)(base+offset)
,还可以执行以下操作
base+=4;
...
clsA->foo( ... );
还有这个
(char*)clsA == (char*)(base+offset)
适用。
我不知道这在c++中是否可能。我知道它可以在ASM (x86/amd64)中完成,但我想要一个具有尽可能多的可移植性的解决方案(我承认仍然接近没有,但总比没有好)。有什么建议吗?
编辑:所以我想我不是很清楚我的问题。其思想是允许动态对象(在堆上分配的对象)在内存中移动。通常情况下,这不会是一个问题,但由于对象不能通过堆栈内存实例化,那么访问对象的唯一方法是通过指向对象底层内存的指针。当数组移动时(在这个例子中,移动了四个字节),从数组中借来的指针不再有效,需要更新。由于这个过程不仅会很长,而且会消耗比我希望的更多的内存,所以我希望能够让类在访问时重新计算它们的内存地址,而不是为每个借来的指针存储一个重定位表。
代表这个概念的程序集将是
;rax stores clsA
mov rcx, rax
shr rcx, 32
mov DWORD PTR[rdx], rax
lea rax, rdx+rcx
push rax
call foo
编辑2:事实证明,对于这种确切的行为类型,还有一个MSVC修饰符。__based声明了一个相对于另一个指针的指针,因此底层内存可以移动,指针仍然有效。
如果我理解你的话,你需要的是指针总是相对于另一个指针。这很简单,但通常是一个坏主意。
template<class T>
struct reloc_ptr {
template<class U>
reloc_ptr(char*& base, int offset, U&& v)
:base(&base), offset(offset)
{new(get())T(std::forward<U>(v));}
T* get() const {return (T*)(*base+offset);}
T* operator->() const {return get();}
void destroy() {get()->~T();}
private:
char** base;
int offset;
};
然后正常用法是这样的
int main() {
char* base = new char[1000];
//construct
reloc_ptr<A> clsA(base,4, "HI"); //I construct the A with the param "HI"
//test
clsA->foo();
//cleanup
clsA.destroy();
delete[] base;
}
注意,reloc_ptr是相对于构建它的char* base
的,所以非常非常小心。如果char* base
变量在函数中,并且函数结束,那么用该char* base
变量构造的所有指针都无效,并且使用它们会使程序做一些奇怪的事情。
与您所问的非常相似的是c++的位置新语法。
位置new在您不希望操作符new分配内存(您已经预先分配了内存,并且您希望将对象放置在那里),但您确实希望构造对象时使用。
在您的示例中,您可能会在内存中的特定位置分配类a,以便然后对其应用方法foo()。
void* memoryBuffer;
...
unsigned int i = 0;
for (uint i= 0; i < N; i += offsetSize){
//initialize a given a specific location in memoryBuffer
A* a = new(memoryBuffer + i)A(...);
//apply foo on that specific memory location
a->foo();
}
这就是使用Eigen将矩阵对象包裹在预分配的数值缓冲区周围的情况。
如果您正在谈论在偏移位置寻址类型为A *
的对象,其他人以某种方式移动的对象,您将使用(clsA+offset)->foo( ... )
之类的东西,其中offset
在sizeof A
单位中,即。你之前的4
实际上是一个1
,因为你可能意味着移动到内存中的"下一个"相邻对象。
如果你说的是实际移动对象,你可以在内存中的新地址上放置new
,然后调用复制构造函数(或为POD调用memcpy
),但这是相当不确定的,这取决于你的对象持有什么,如果它坚持指针的所有权,当你调用放置delete
时,内存被释放,你很SOL。
我再怎么强调也不为过,告诉我们你想要完成什么因为可能有更好的方法,这与这里的谚语相悖
- 将数组的地址分配给变量并删除
- 空基优化子对象的地址
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 如何在c++程序中找到函数的地址
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 被解释为低级别const的const对象的地址
- 将地址分配给本地指针后,公共对象的变量将消失
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 内联程序集printf将整数解释为地址
- 为什么指针不写入类的地址?
- 如何在C++中获取该对象的类声明中对象的地址?
- 通过按地址访问变量
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- C++ Qt MingW 错误的重新定位0xc rdata 部分中的地址
- 错误的重新定位地址0x0在 python.data C 扩展中
- 链接器错误:未定义的引用/错误的重新定位地址/ld返回1个出口
- 如何快速重新定位偏移地址
- c++对象的动态地址重定位
- 未定义的引用,但(动态)库被链接.(可能是坏的重定位地址错误)