c++ - 使用 std::strtod 后发生奇怪的事情

标签 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 是一个类,它有一个类型为 void 的属性 value,一个属性 line 类型 int,以及自定义枚举 token_type 的属性 type。在第一行中,我初始化一个新的,将一个空指针传递给它的构造函数(因为我们仍然必须创建它),枚举 token_type 的值(number 因为这个标记属于那种类型),以及我们在 lambda 中捕获的当前行。

i 是一个类型为 const char* 的指针,它指向我们正在检查的当前字符。当我们调用此 lambda 函数时,它保证指向一个可打印字符。

printf 用于调试;

所以我想做的是:创建一个内部类型为 number 的新 Token;询问 strtod 我们是否可以从当前位置构建一个数字;然后检查 strtod 是否返回了一个非零值,在这种情况下,我们将该值存储在新的 Token 中,将我们指向的字符的位置提前到数字后面的字符,返回Token

如果 strtod 返回的是零值,我们必须仔细检查该零值是因为找到了实际的 0,还是无法构建数字。因此,我们检查指向数字后字符的指针是否指向与当前位置相同的字符:如果为真,则意味着 strtok 没有推进该指针,这意味着根本没有数字找到了(并且我们删除了分配的值并返回一个空指针来表示)。否则,这意味着找到了一个 0,因此我们将其存储、前进并返回。

问题是,当我尝试引用 after_number 时,我确实 每次 都会收到段错误:也就是说,如果我调用 buildnumberi 指向像 "111" 这样的字符串,在它打印 "Advancing position" 后我得到了一个段错误。如果我在 i 指向像 "+0.0""abc()" 这样的字符串时调用它,我会在它之后得到一个段错误打印 “Value was 0, comparing position to after number”

这是为什么呢? after_number 指向的指针会发生什么变化?我做错了什么?

最佳答案

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

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

正确的做法如下:

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

这实际上创建一个 char * 变量,strtod 可以将结束指针放入其中,并将它的地址传递给 strtod。退出时,after_number 将保存指向停止数字计算的结束字符的指针(希望这将是指向所提供的实际字符串结尾的指针,*after_number == '\0'.

关于c++ - 使用 std::strtod 后发生奇怪的事情,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39555771/

相关文章:

c++ - 删除指针问题

c++ - 编译器是否允许在运行时调用立即(consteval)函数?

c++ - 是否推荐具有 copy-and-swap 习语和自赋值检查的复制赋值运算符?

node.js - Heroku 上的 Node 应用程序段错误:std::bad_alloc 和退出代码 134

c - 键盘处理程序导致段错误 (djgpp)

android - android NDK中的颜色叠加

c++ - 堆栈在哪里实现?

c++ - C++11 的标准库会有前向声明头吗?

c++ - 为什么没有透明的 C++1x std::map::at?

C 段错误,任何人都可以帮助我确定原因吗?