在我的程序中,我有一个垃圾收集器,我需要跟踪哪些对象保存在我的程序中的局部变量上,以避免在它们存活时进行垃圾收集。
虽然我使用了创建复合类型的链表,但我刚刚意识到C ++语言必须保留该链表,因为它自己的析构函数目的尤其与异常处理有关。
所以我想通过使用C ++异常处理程序保存的信息来简化我的代码。有可行的方法吗?
如果没有关于g ++和clang的信息?
顺便说一下,当我使用多任务处理时,我应该能够为每个任务执行此操作(这些正在等待垃圾收集器运行时)。
我真正需要的是遍历具有析构函数设置的局部变量(并以非破坏性方式执行)。
答案 0 :(得分:0)
这就是析构函数的用途。如果您需要知道某个对象(无论是在堆上还是堆栈上)何时超出范围,那么您将使用析构函数。
答案 1 :(得分:0)
通过检查gnu gcc编译器发出的代码,我发现有关执行哪些析构函数的信息以代码形式“保存”,代码知道它必须要破坏它并处理它。因此,重新获得这些信息太难了。
实现可能有所不同,代码可能已作为返回地址推送到处理器堆栈中,析构函数代码的地址以及结构实例的地址。
所以我准备放弃努力,但我找到了另一条骇客的路线。
我注意到gnu编译器在16字节的边界上对齐堆栈上的结构。 由于我的结构是8个字节,因此还有8个未使用的字节。 所以我认为我可以使用它们来跟踪堆栈上分配的对象。 必须要说的是,根据编译标志为-m64,-mx32的内容会发生变化,必须加以修改。
我设法让代码编译并在-m64和-mx32模式下工作。
它不是纯粹的“C ++”(恰恰相反),但代码有效并具有预期的效果。
#include <stdio.h>
#define ONSTACK(x) (((size_t)x)&0xf0000000)==0xf0000000
struct A;
void* P=nullptr;
struct A{
static int i;
long long a;
A(){
if(ONSTACK(this)){
*(void**)(this+1)=P;
P=(void*)(this+1);
}
printf("this=%p\n",this);
a=0x1111111111111111*i;i++;
}
~A(){
if(ONSTACK(this))
P=*(void**)(this+1);
*(void**)(this+1)=nullptr;
a=0xFFFFFFFFFFFFFFFF;}
};
int A::i=0xA;
void* p;
void r1(){
A x;int xx=0x66666666;
A y;int yy=0x77777777;
A z;int zz=0x88888888;
int b=0x2222222222222222;
printf("hello world %p\n",&b);
for(void* i=P;i!=nullptr;i=*(void**)i){
printf("a=%llX\n",(((A*)i)-1)->a);
}
}
void r2(){
long long r2a;
r2a=0x3333333333333333;
r1();
}
A A0;
int main(int argc, char **argv)
{ int i;p=(char*)&i-0x100;
printf("sizeof(P)=%i\n",sizeof(P));
r2();
}