gpt4 book ai didi

c - 将寄存器转储到堆栈中以进行保守的堆栈扫描

转载 作者:太空狗 更新时间:2023-10-29 17:13:22 24 4
gpt4 key购买 nike

我正在用 C 语言编写一个非侵入式保守 GC,我对其堆栈扫描阶段的正确性有些担忧。

具体来说,在没有启用编译器优化的情况下,它工作正常,因为每个局部变量(指向一个对象)都“可预测地”分配在堆栈上。在 -O3 中,GC 丢失了一些有效的引用,我认为这是由于编译器选择使用寄存器(而不是 GC 扫描的堆栈)来处理某些变量和函数参数通过并且 GC 还没有(还)被编程来处理它。 (如果您怀疑这仍然不应该发生并且我误解了问题的根源,请告诉我。)

除了一些基本要求(必须对 GC 对象使用 GC_malloc 而不是 malloc,不要从非 GC 堆指向 GC 堆,并且,当然,不是显式调用 free),GC 不应该有来自客户端代码或编译器的任何更多要求。因此,要求客户端代码提供任何额外的特殊模式不是一种选择。同样,强制使用此 GC 的程序使用特殊的编译器标志(抑制堆栈优化)进行编译,充其量应该是最后的选择。解决了这两个问题后,我的问题就形成了。

我正在尝试找到一种方法让 GC 无缝处理 -O3 情况(通过堆栈优化)。这是我的思路(假设,更准确地说):

  1. 无论 GCC(或任何有效的编译器)在优化方面走多远,都不会走得太远以至于损害程序的正确性。
  2. 如果 [1] 成立,我相信(至少在 C 的实际实现中)如果可达(在任何调用级别分配为本地)变量要始终保持可访问性,它必须在堆栈上或在当前寄存器集中,但实际上不能在其他任何地方。
  3. 如果 [2] 成立,它应该意味着在 GC 周期开始时简单地将所有寄存器转储到堆栈将保证后续堆栈扫描现在也能找到以前丢失的引用。
  4. 此外,如果 [1] 和 [2] 成立,那么如果编译器让任何变量被覆盖(在基于寄存器的情况下,主要是),这意味着它已经执行了某种级别的代码分析并且它已证明该变量未在该函数的其他任何地方使用。因此,从这个意义上说,如果我们没有在堆栈或寄存器转储中看到变量,即使它仍在范围内(理论上),这也不应该引起警报(对我而言),因为编译器已经只是通过摆脱死引用来帮助 GC。

问题 #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);

这意味着您存储的指针根本不指向 block 的开头。

关于c - 将寄存器转储到堆栈中以进行保守的堆栈扫描,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14512790/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com