c++ - 检查 NULL 时要忽略多少位?

标签 c++ segmentation-fault low-level

以下使用 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:这是一个半假设的情况。导致我想到这个的错误在我发布之前已经修复,但我以前遇到过它并且正在考虑将来如何使用它。

为了论证可以假设的事情:

  • 如果调用 Set 时使用了 seg-v 的东西,那是一个错误
  • Set 可能会被代码调用,这不是我要修复的工作。 (例如,我提交了一个错误)
  • Set 可能会被我试图修复的代码调用。 (例如,我在调试工作中添加完整性检查。)
  • 以不提供有关调用 Set 位置的信息的方式调用我。 (即允许 Get 到 seg-v 并不是调试任何东西的有效方法。)
  • 代码不需要可移植或捕获 100% 的错误指针。它只需要经常在我当前的系统上运行,足以让我找到哪里出了问题。

最佳答案

除 NULL 外,没有可移植的方法来测试任何无效指针。在你对它做任何事情之前,评估 &ip[3] 会给出未定义的行为;唯一的解决方案是在对指针进行任何运算之前 测试 NULL。

如果你不需要可移植性,也不需要保证你捕获所有的错误,那么在大多数主流平台上你可以检查地址是否在内存的第一页内;通常将 NULL 定义为地址零,并保留第一页以捕获大多数空指针取消引用。在 POSIX 平台上,这看起来像

static size_t page_size = sysconf(_SC_PAGESIZE);
assert(reinterpret_cast<intptr_t>(i) >= page_size);

但这不是一个完整的解决方案。唯一真正的解决方案是首先修复任何滥用空指针的问题。

关于c++ - 检查 NULL 时要忽略多少位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3720184/

相关文章:

用于访问无符号整数的字节/字的 C++ 类

java - 操纵发送到监视器的信号

c - 从服务器向客户端发送文件文本时出现段错误

C++类指针删除段错误

python - 如何在windows下打开磁盘读取低级数据?

c++ - Windows 上通过 C++ 的唯一 CPU ID

仅用于 UI 的 C++ 跨平台移动框架

c++ - 黄色检测程序断言失败

c++ - 工厂模式中的子类特定访问

c++ - 任何想法如何使 C++ 在内核错误上抛出异常