以下使用 seg-V 崩溃:
// my code
int* ipt;
int bool set = false;
void Set(int* i) {
ASSERT(i);
ipt = i;
set = true;
}
int Get() {
return set ? *ipt : 0;
}
// code that I don't control.
struct S { int I, int J; }
int main() {
S* ip = NULL;
// code that, as a bug, forgets to set ip...
Set(&ip->J);
// gobs of code
return Get();
}
这是因为虽然i
不是NULL
它仍然无效。NULL
如果调用代码从指针中获取数组索引操作的地址,也会发生同样的问题。
对此的一种解决方案是修剪低位:
void Set(int* i) {
ASSERT((reinterpret_cast<size_t>(i))>>10);
ipt = i;
set = true;
}
但是我应该/可以去掉多少位?
编辑,我不担心未定义的行为,因为无论如何我都会在这种情况下中止(但比 seg-v 更干净)。
FWIW:这是一个半假设的情况。导致我想到这一点的错误在我发布之前已修复,但我之前遇到过它并且正在考虑将来如何使用它。
为了论证而可以假设的事情:
- 如果用 seg-v 的东西调用 Set,这是一个错误
- Set 可能会被我不负责修复的代码调用。(例如我提交了一个错误)
- 我试图修复的代码可能会调用 Set 。(例如,我在调试工作中添加了完整性检查。)
- 以不提供有关调用 Set 的位置的信息的方式调用我。(即允许 Get 到 seg-v 不是调试任何东西的有效方法。)
- 代码不需要是可移植的或捕获 100% 的错误指针。它只需要经常在我当前的系统上运行,就足以让我找到哪里出了问题。