使用std :: strtod后会发生奇怪的事情

时间:2016-09-18 08:48:01

标签: c++ c++11 segmentation-fault strtod

这是一个小的lambda函数,我在我的词法分析器的代码中用作辅助函数:

auto buildnumber = [&line, &i] () -> Token* {
    Token* new_number = new Token(nullptr, number, line);

    char** after_number = nullptr;
    double* value = new double(std::strtod(i, after_number));

    printf("Value got: %f\n", *value);
    printf("Comparing it to 0\n");
    if (*value == 0.0) {
        printf("value was 0, comparing position to after number\n");
        if (i == *after_number) {
            printf("No number detected\n");
            delete value;
            delete new_number;
            return nullptr;
        }
    }

    printf("Value was different from 0, storing it in Token\n");
    new_number->value = (void*) value;
    printf("Advancing position\n");
    i = *after_number;
    printf("Returning\n");

    return new_number;
};

这里有一点背景:Token是一个类value属性void的类,line类型属性int,以及自定义枚举type的属性token_type。在第一行中,我初始化一个新的,传递给它的构造函数的值为空指针(因为我们仍然需要创建它),枚举值token_typenumber因为这个令牌是那个类型),以及我们在lambda中捕获的当前行。

iconst char*类型的指针,指向我们正在检查的当前特征。当我们称这个lambda函数时,它保证它将指向一个可打印的字符。

printf用于调试目的;

所以我要做的是:创建一个新的Token内部类型number;问strtod我们是否可以从当前位置建立一个数字;然后检查strtod是否返回了非零值,在这种情况下,我们将该值存储在新的Token中,提升我们直接指向该字符的字符的位置。编号,并返回Token

如果strtod返回零值,我们必须重新检查零是因为找到了实际的0,或者是否可以建立数字。因此,我们检查数字后指向字符的指针是否指向与当前位置相同的字符:如果它是真的,则表示strtok没有推进该指针,这意味着没有找到了数字(我们删除了分配的值并返回一个空指针指示信号)。否则,这意味着找到了0,因此我们存储它,前进并返回。

问题是,我在每次时间内得到一个Segfault错误我试图尊重after_number:也就是说,如果我在buildnumber点时调用i对于像"111"这样的字符串,我在打印"Advancing position"后得到一个段错误。如果我在i指向"+0.0""abc()"之类的字符串时调用它,则在打印"Value was 0, comparing position to after number"后会出现段错误。

为什么? after_number指向的指针会发生什么?我做错了什么?

1 个答案:

答案 0 :(得分:6)

你已经将after_number定义为指向字符指针的指针,然后直接使用 ,当它实际上没有指向任何有用的东西时。

问题在于你基本上告诉strtod不要实际存储结束指针(因为你提供了nullptr作为存储它的地址in),然后你继续尝试取消引用它 - 它仍然是nullptr,因此你将得到未定义的行为。

正确的方法如下:

char *after_number;
double *value = new double(std::strtod(i, &after_number));

这实际上创建了 char *变量,strtod可以将结尾指针放入其中,并将其地址传递给strtod。退出时,after_number将保持指向停止数值评估的结束字符的指针(希望,这将是指向提供的实际字符串末尾的指针,*after_number == '\0'