2

在 C 语言中,可以使用诸如this one之类的方法将 -1 值(例如 0xFFFFFFFF)填充到指针中,并期望在运行时永远不会分配这样的内存地址吗?

这个想法是将指针值用作内存地址,除非它具有这个“特殊”-1 值。即使指针为 NULL,也应将指针视为内存地址(在这种情况下,它指向的对象尚未构建)。

我知道这可能与平台有关,但有问题的程序预计可以在 Linux、Windows 和 MacOSX 中运行。

手头的问题比这里描述的要大得多,所以评论或回答这个方法没有用的问题。我知道这有点老套,但替代方案是一个主要的重构:/

提前致谢。

4

2 回答 2

9

它是 GRAS(通常被认为是安全的)。没有主要操作系统会分配与您选择的哨兵冲突的内存。然而,有一些病态的情况下,做出这种假设是无效的。例如,病态的 C++ 编译器可能会选择从 0xFFFFFFFF 开始堆栈,而不会违反规范中的任何约束。

在健全的操作系统范围内,几乎不可能将 0xFFFFFFFF(或其 64 位等效项)作为有效的内存地址。它不能是数组的有效内存地址(C++ 规则禁止它)。从技术上讲,它可能是在空间末尾分配的对象的 char 的有效索引,但有两件事可以防止这种情况发生。

  1. 大多数操作系统都有一些填充
  2. 大多数操作系统使用高内存值作为内核内存。

如果您有机会将全局值用作哨兵,则可以保证它是安全的。

char sentinel;

char* p = "Hello";
char* p2 = 0; // null pointer
char* p3 = &sentinel;

if (p3 == &sentinel)
    cout << "p3 was a sentinel" << endl;
于 2014-07-08T17:01:27.883 回答
4

定义与其他有效地址不相符的标记值的一种方法是使用静态变量:

static t sentinel;
t *p = &sentinel;

如果您要假设一个平坦的地址空间并且所有指针具有相同的宽度,您可以通过声明sentineltypechar而不是t.


要回答您的问题(t*)-1

  • -1有类型int。我会推荐(t*)(uintptr_t)-1,即使对于 64 位平面地址空间,它也更有可能是最后一个地址。

  • 它不是很干净,但它应该适用于所有常见的体系结构,因为只要编译器打算使用无符号比较汇编指令(通常这样做)比较指针,对于a编译器可能希望放置的任何对象地址空间的末尾,&a + 1必须比较大于 &a. 实际上,这可以防止最后一个地址用于存储任何内容。

于 2014-07-08T17:29:50.013 回答