执行以下操作是否安全?
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个字节并不危险。
答案 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
会做得很好。