简体   繁体   English

Strtol在溢出转换时未设置errno

[英]Strtol doesn't set errno on overflow conversion

My strtol function fails to set errno during overflown conversion. 我的strtol函数无法在溢出转换期间设置errno。

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <getopt.h>
#include <errno.h>
#include <stdlib.h>    

int main(int argc, char **argv) {

    errno = 0;
    int e = strtol("1000000000000000", NULL, 10);
    printf("%d %d\n", errno, e);

    return 0;
}

returns 回报

0 -1530494976

What do I do wrong? 我做错了什么?

Compiler 编译器

gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2

Options 选项

gcc -Wall -std=gnu99 -O2

There is nothing wrong with the implementation of strtol() but there is with your code. strtol()的实现没有错,但是您的代码却有错。

The return type of this function is long (see the trailing l ) and apparently the value 1000000000000000 can be represented by the long integer type. 此函数的返回类型很long (请参见尾部l ),显然值1000000000000000可以由long整数类型表示。 However the return value is assigned to e whose type is int which is unable to represent this value. 但是,将返回值分配给类型为int e ,它无法表示该值。 What then happens is implementation-defined. 然后发生的事情是实现定义的。

So change int e to long e and "%d %d\\n" to "%d %ld\\n" . 因此,将int e更改为long e ,将"%d %d\\n"更改为"%d %ld\\n" If you want to keep it as int , then you have to check if the value is outside of its range of representable values by yourself: 如果要将其保留为int ,则必须自己检查该值是否超出其可表示值的范围:

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h>  // for INT_{MIN,MAX}
int
main(void)
{
    errno = 0;
    long f = strtol("1000000000000000", NULL, 10);
    if (errno == ERANGE) {
        puts("value not representable by long (or int)");
    } else if (f < INT_MIN || f > INT_MAX) {
        puts("value not representable by int");
    } else {
        int e = f;
        printf("%d\n", e);
    }
}

You are doing well but you are not checking the errno value for strtol but for printf() ....Not understand let me explain... After long f = strtol("1000000000000000", NULL, 10); 您做得不错,但您没有检查strtolerrno值,而是printf() ...。不明白,请允许我解释一下... long f = strtol("1000000000000000", NULL, 10); statement you have to first save the value of errno. 语句,您必须首先保存errno的值。 Because after this statement you are going to call printf() statement that also set errno accordingly. 因为在此语句之后,您将调用也会相应设置errno printf()语句。

printf("errno is: %d\n", errno); 

So in this statement "errno" gives the error indication for printf() not for strtol() ... To do so save "errno" before calling any library function because most of the library function interact with "errno". 因此,在此语句中,“ errno”给出了printf()的错误指示,而不是strtol()的错误指示。为此,在调用任何库函数之前保存“ errno”,因为大多数库函数都与“ errno”交互。 The correct use is : 正确的用法是:

long f = strtol("1000000000000000", NULL, 10);
int saved_error = errno;       // Saving the error...
printf("errno is: %d\n", saved_error);

Now check it. 现在检查一下。 It will give correct output surely...And one more thing to convert this errno to some meaningful string to represent error. 它肯定会给出正确的输出...还有另一件事将这个errno转换为一些有意义的字符串来表示错误。 Use strerror() function as : 使用strerror()函数如下:

printf("Error is: %s\n", strerror(saved_error)); 

Cremno's answer is correct but this is more generic. Cremno's answer是正确的,但这是更通用的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM