0

这是一个小的 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是一个具有valuetypevoid属性line、 typeint属性type和自定义 enum属性的类token_type。在第一行中,我初始化了一个新的传递给它的构造函数的值的空指针(因为我们仍然必须创建它),枚举的值token_typenumber因为这个令牌属于那种类型),以及我们捕获的当前行在拉姆达。

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

printfs 用于调试目的;

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

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

问题是,我每次尝试尊重时都会收到 Segfault 错误after_number:也就是说,如果我调用buildnumberwheni指向一个类似 的字符串"111",我会在它打印后得到一个 segfault "Advancing position"。如果我在i指向类似"+0.0"or的字符串时调用它"abc()",则在打印后会出现段错误"Value was 0, comparing position to after number"

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

4

1 回答 1

6

您已将其定义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'.

于 2016-09-18T08:53:13.830 回答