The*_*kis 7 c stack garbage-collection cpu-registers compiler-optimization
我在C中写了一个非侵入性的保守GC,我对它的堆栈扫描阶段的正确性有些担忧.
具体来说,没有启用编译器优化,它工作正常,因为每个局部变量(指向一个对象)在堆栈上"可预测地"分配.在-O3,GC错过了一些有效的引用,我认为这是因为编译器选择使用寄存器(而不是GC扫描的堆栈)来处理某些变量和函数参数传递而GC不是(但是编程处理.(如果您怀疑这仍然不应该发生,并且我误解了问题的根源,请告诉我.)
除了一些基本要求(必须使用GC_malloc而不是mallocGC对象,不指向来自非GC堆的GC堆,当然,没有明确调用free),GC不应该有来自客户端的任何更多要求代码或编译器.因此,不需要客户端代码中的任何其他特殊模式.类似地,强制使用此GC编译的程序使用特殊的编译器标志(抑制堆栈优化)应该是最后的选择.有了这两个,这就是我的问题的构建.
我正试图找到一种方法使GC -O3无缝地处理案例(使用堆栈优化).这是我的思路(假设,更准确地说):
问题1:是否所有我的假设4是否正确?
问题2:强制注册转储的最便携方式是什么?我发现一些消息来源声称一个简单的setjmp电话会产生这种效果.它是否正确?
Q1. 是的,我相信你的所有四个陈述都是正确的(至少如果我们忽略编译器错误的话!)
Q2。setjmp 将保存一些寄存器,但不一定是所有寄存器。但是,它应该足以满足您的目的,因为任何未由 setjmp 保存的寄存器都应该保存在堆栈上。
我猜如果有人在某个缓冲区中存储看起来像地址的东西,即使事实并非如此,你的方案可能会出错。
您还必须记住,有时人们会用指针做“有趣”的事情。例如
struct blah
{
size_t size;
char *file;
int line;
};
struct blah *p = malloc(sizeof(struct blah) + size);
... more lines of code goes here to fll in size, file and line in blah.
void *np = (p+1);
Run Code Online (Sandbox Code Playgroud)
这意味着您存储的指针根本不指向块的开头。