【问题标题】:Testing `errno` after calling `strtol` returns "No such process"调用 `strtol` 后测试 `errno` 会返回“没有这样的过程”
【发布时间】:2014-05-22 07:41:10
【问题描述】:

即使字符串转换成功,测试errno会返回一个指示错误的值:

#include <stdlib.h>
#include <sys/errno.h>

const char* numberString = "7";
char* endPtr;
errno = 0;
long number = strtol(numberString, &endPtr, 10);
NSLog(@"%ld", number);
if (errno) {
    perror("string to integer conversion failed");
}

输出是(在模拟器上,iOS 7)

$ 2014-05-22 09:27:32.954 Test[2144:60b] 7
$ string to integer conversion failed: No such process

设备上的行为类似。

strtolman page 在评论中说:

返回值
strtol()、strtoll()、strtoimax() 和 strtoq() 函数返回转换的结果, 除非该值会下溢或溢出。如果无法执行转换,则返回 0 并 全局变量 errno 设置为 EINVAL(最后一个功能不能在所有平台上移植)。如果 发生上溢或下溢,errno 设置为 ERANGE,函数返回值被钳位 根据下表。

目前还不清楚这对 iOS 究竟意味着什么。这里有什么见解吗?

编辑:

原来函数调用NSLog确实设置了errno。所以,@Mat 在他的回答中,cmets 说“在调用一个不相关的函数(这里是NSLog)之后测试errno 时,所有的赌注都被取消了。

【问题讨论】:

  • 看起来errno 仅在strtol 失败时才设置 - 因为strtol 成功,那么您不应该尝试读取errno

标签: ios objective-c errno strtol


【解决方案1】:

如果无法进行转换,则返回 0

你不是那种情况,返回的是 7。

如果发生上溢或下溢,...根据下表对返回值进行钳位。

你也不是那种情况。

所以strtol 没有失败。检查errno 毫无意义。记录在失败时设置errno 的函数将在失败的情况下执行此操作。当没有发生故障时,errno 的值在“道德上”是未定义的。不要检查它。

strtol 是一个特例。 POSIX 需要以下内容:

如果成功,这些函数不会改变errno的设置。

所以你的例子应该没​​问题。除了您在strtol 调用和您对errno 的检查之间调用一个函数。如果您 100% 确定该函数本身不会更改 errno,或调用可能设置它的另一个函数,那么在这种非常特殊的情况下您会没问题(记录的函数不会更改 errno,以防万一成功 - 这不是常态)。显然情况并非如此。 NSLog 很可能会在某个时候使用一些系统调用,而那些(通常)不能保证不会改变 errno

【讨论】:

  • 这是有道理的。顺便说一句,cppreference.com 上有一个示例,这似乎与我的示例很不正确:strtol example
  • 哼。奇怪,这通常是一个很好的参考。让我看看我是不是错过了什么。
  • @CouchDeveloper:是的,抱歉,我的回答实际上并不正确。我相信现在是这样,并且“一般建议”确实适用 - 在成功的情况下不要测试 errno,并在调用失败后立即检查 errno。 cppreference 中的该示例需要在循环中的 strol 调用有效之前将 errno 重置为零,除非我遗漏了其他内容:-/
  • 感谢您的更新。请注意,我也将errno 设置为零调用strtol。尽管strtol 不应该碰errno,因为它成功了,它返回ESRCH(“没有这样的过程”)。 ESRCH 甚至没有在手册页中列为strtol 的可能错误代码之一。
  • @CouchDeveloper:您正在调用strtol 和您的errno 检查之间的函数。所有赌注都取消了。
猜你喜欢
  • 2019-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多