C 将指针与(无符号)-4000L进行比较的目的

C 将指针与(无符号)-4000L进行比较的目的,c,pointers,C,Pointers,在开源组件中 #定义为错误(ptr)((无符号长)ptr>(无符号长)-4000L) 上述语句用于检查指针的有效性,如下所示 json_object* reply = json_object_new_object(); if (!reply || is_error(reply)) { . . . //error handling } 将指针与(unsigned long)-4000L进行比较如何验证指针?看起来作者正在对虚拟内存的分配位置进行特定于平台的假设。在这种情况下,假设一个有效指针将

在开源组件中

#定义为错误(ptr)((无符号长)ptr>(无符号长)-4000L)

上述语句用于检查指针的有效性,如下所示

json_object* reply = json_object_new_object();
if (!reply || is_error(reply))
{
 . . . //error handling
}

将指针与
(unsigned long)-4000L进行比较如何验证指针?

看起来作者正在对虚拟内存的分配位置进行特定于平台的假设。在这种情况下,假设一个有效指针将始终大致位于可寻址空间的前4GB内[编辑:这是基于
long
为32位的(可疑)假设。]

您的特定示例似乎来自一个名为OpenWebOS的东西。我不知道那是什么;但是,如果他们是操作系统的制造商,那么他们就可以制定自己的规则,来决定指针的去向。也许操作系统甚至有一个约定,超过某个值的地址被用来表示错误


如果你想编写可移植的代码,在尝试类似的技巧之前,你应该仔细考虑。

除非在某些非常特殊的情况下,否则不会这样做-也许最初的作者有一个指针错误,他的指针在某种程度上被破坏了,它们在这个比较的“范围”内,或者他的编译器和操作系统有一些奇怪的非标准指针验证或解释“特性”

-解释为无符号32位整数的4000是0xfffff060


如果它是在内核中运行的代码,它可能与用户区/内核内存空间的划分有关(即地址空间的上半部分和下半部分),但即使这样,它也可能是错误的。我的钱在第一个主意上。

错了!不应该有任何类似(unsigned long)-4000L的值。它应该是NULL(未分配)或非NULL(具有有效值)。每当指针被释放时,它都应该恢复为NULL,我的意思是重新分配给NULL以避免指针悬空。非空检查值足以确定指针是否有效并指向某些有效内容。

原因似乎是他们使用指针值来包含“指针或错误值”

:


因此,使用该特殊值的原因是,它们可以保存“指向结构的指针或错误代码”。这也可以通过联合、结构或其他方式完成,但他们选择了这种方式。

也许这就是json函数的工作方式并返回退出代码。版本0.3提到“修复错误指针检入的指针算术错误is_error()宏”,请参阅。但这并不能解释。多么糟糕的api设计啊。让你想知道他们还放了什么“宝石”…正如Wumpus Q Wumbley所说,这并不少见,尽管在操作系统中比在用户代码中更常见。另请参见标记的指针,@Joe可能为操作系统代码所接受,但在JSON解析器上并非如此
json\u object*json\u object\u new\u object(int*optionalErrorCode)
会好得多。你是如何定义“4GB地址空间”的?我错了,我认为在大多数现代系统(即使是64位系统)上,
long
是32位的。在这种情况下,
(unsigned long)-4000
大约是4G。但是,在一些非常常见的系统上,
long
可以是64位。在这种情况下,它大约是16 EB。为什么是32位整数?消息人士说
-4000L
。这无关紧要。因为它是负值,所以只需在前面加上“ff”。作为一个64位无符号整数,它是0xFFFFFFFFFFF060。问题不是“我应该吗?”而是“他们为什么这样做?”。Linux在内核中做了一些非常类似的事情,这可能是这些json人的想法。内核必须知道所有支持的体系结构的指针格式,所以它可以保证这个技巧有效。
struct json_object* json_tokener_parse(const char *str)
{
  struct json_tokener* tok;
  struct json_object* obj;

  tok = json_tokener_new();
  obj = json_tokener_parse_ex(tok, str, -1);
  if(tok->err != json_tokener_success)
    obj = error_ptr(-tok->err); // <<<<<---
  json_tokener_free(tok);
  return obj;
}
 new_obj = json_tokener_parse("{ foo }");
  if(is_error(new_obj)) printf("got error as expected\n");