0
点赞
收藏
分享

微信扫一扫

errno 的坑

fbd4ffd0717b 2023-09-12 阅读 41


由于 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 条评论