errno 的坑

来源:互联网 发布:淘宝卖的6s为什么便宜 编辑:程序博客网 时间:2024/06/05 12:42

由于 strtoll, strtoull 返回值不能标识处理是否成功,所以需要借助 errno, 看下面这段代码:

#include <stdio.h>#include <stdlib.h>#include <errno.h>int main(int argc, char* argv[]){    if (argc != 2)    {        printf("Usage: %s <number>\n", argv[0]);        return -1;    }        // errno was set to some value in somewhere, but we don't know.    errno = ERANGE;        char * pEnd;    long long value = strtoll(argv[1], &pEnd, 0);    if (ERANGE == errno)        printf("out of range\n");    else        printf("%lld\n", value);    printf("---------------\n");    // 1 -9223372036854775809 -9223372036854775808 9223372036854775807 9223372036854775808 9223372036854775807.2        return 0;}
输入 1 时误判为越界,所以在用 errno 时必须调用放手动置 errno 为 0, 系统提供的 api 内部是不会去将 errno 置为 0 的。

因为 errno 是全局的,整个线程都生效,在一个很大的项目中,errno 在哪里不小心被置为非 0 值是极有可能的,因此,需要使用者非常小心。


正确的使用方法:

Since strtoul() can legitimately return 0 or LONG_MAX (LLONG_MAX for strtoull()) on both success and failure, the calling  program  should  set errno to 0 before the call, and then determine if an error occurred by checking whether errno has a non-zero value after the call.

#include <stdio.h>#include <stdlib.h>#include <errno.h>int main(int argc, char* argv[]){    if (argc != 2)    {        printf("Usage: %s <number>\n", argv[0]);        return -1;    }    // errno was set to some value in somewhere, but we don't know.    errno = ERANGE;        // [Note] You must set errno to 0 before calling.    int errnoBackup = errno;    errno = 0;        char * pEnd;    long long value = strtoll(argv[1], &pEnd, 0);    if (ERANGE == errno)        printf("out of range\n");    else        printf("%lld\n", value);    printf("---------------\n");    // 1 -9223372036854775809 -9223372036854775808 9223372036854775807 9223372036854775808 9223372036854775807.2    // [Note] Recovery errno.    errno = errnoBackup;        return 0;}


0 0