保留指针地址(使用特殊情况)

时间:2012-03-14 10:55:57

标签: c++ memory memory-address

执行以下操作是否安全?

MyClass* p = WantItInCase1();
if (p == NULL)
    p = 0x1;
else
   p = WantItInCase2();
if (p == NULL)
   p = 0x2;
...
CheckCases (p);  // we check '0x1' and '0x2' cases and otherwise process 'p' as normal object

我遇到MyClass个对象无法处理CheckCases()中所需的所有变体的情况。那么为了避免额外的参数,是否可以使用这种方法?至少我需要一系列不能用于new分配的地址。

---更新---

考虑到答案,我决定采取一些“棘手”的方法:

// somewhere in global definitions:
const MyClass* P_CASE_1 = (MyClass*) new int;
const MyClass* P_CASE_2 = (MyClass*) new int;
...
// previous code piece:
MyClass* p = WantItInCase1();
if (p == NULL)
    p = P_CASE_1;

这将是内存安全的,每个P_CASE_#泄漏4个字节并不危险。

4 个答案:

答案 0 :(得分:2)

对于海湾合作委员会,这种分配是“默认”禁止的。由于标志-fpermissive,你必须强制编译。

我认为这不是“好”。我更喜欢这种方法:

MyClass* p = WantItInCase1();
int flag;
if (p == NULL)
    flag = 0x1;
else
   p = WantItInCase2();
if (p == NULL)
   flag = 0x2;
...
CheckCases (flag);

当然使用了更多“内存”,但今天,4字节是什么?

所以为了回答你的问题,这种作业非常气馁......但是你的程序可能有效......

如果您尝试读取p(在您的checkclass方法中),您将编写如下内容:

if(p == 0x1) ...

这种行会产生一个警告(使用GCC),因为你将一个指针与一个整数进行比较,所以:一个警告+ -fpermissive flag =不要这样做!

答案 1 :(得分:0)

这取决于操作系统: - )

要说清楚:在Windows 32位上,最后一个gb的地址空间始终保留给内核,因此您可以使用其地址供您使用。通常它将是最后2 GB的地址空间,但通过开关/3GB,您可以更改它。内核中使用了类似的技巧来处理某些数据结构。

我不会这样做: - )

我要补充一点,可能0x1,0x2,0x3非常安全,因为操作系统给你的地址通常至少是32位对齐,0x0是为特殊用途定义的,所以接下来的三个字节不会被分配在一个内存块中。 Aaah ......太难解释了。假设C运行时从OS获取内存,而“标准”OS将不会在0x0-0x3范围内提供内存。

答案 2 :(得分:0)

这是特定于实现的。在针对Windows的Microsoft编译器上,它将起作用。 MAKEINTRESOURCE宏基本上做同样的事情。

答案 3 :(得分:0)

这不仅是未定义的行为,而且是高度平台特定的,因此它应该真正避免,您可以使用自定义引用计数指针(其中负参考用于您的特殊情况)或辅助变量甚至是一些花哨的do{}while(0)构造。

如果你确实想要标记指针,那么windows下的第一页(64Kb)是保留的,永远不会在用户空间或内核中分配。对于内核空间保留的地址的MSB也是如此。然而,你需要做一些演员,因为uintptr_t会做得很好。