use*_*072 0 c++ segmentation-fault strtod c++11
这是一个小的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;
};
Run Code Online (Sandbox Code Playgroud)
这里有一点背景:Token是一个具有value类型void属性line,类型int属性type和自定义枚举属性的类token_type.在第一行中,我初始化一个新的传递给它的构造函数的值为空指针(因为我们仍然需要创建它),枚举的值token_type(number因为这个令牌属于那种类型),以及我们捕获的当前行在lambda.
i是一个类型的指针const char*,指向我们正在检查的当前特征.当我们调用这个lambda函数时,它保证它将指向一个可打印的字符.
该printfs为用于调试的目的;
所以我要做的是:创建一个新Token的内部类型number; 问strtod我们是否可以从当前位置建立一个数字; 然后检查是否strtod返回非零值,在这种情况下我们将该值存储在new中Token,将我们指向的字符的位置直接提前到数字后面的字符,然后返回Token.
如果strtod返回一个零值,我们必须重新检查,如果零是因为找到了实际的0,或者相反没有数字可以建立.因此,我们检查数字后指向字符的指针是否指向与当前位置相同的字符:如果是,则表示strtok没有超前指针,这意味着根本找不到任何数字(我们删除已分配的数字)值并返回一个空指针指向信号).否则,这意味着找到了0,因此我们存储它,前进并返回.
问题是,从字面上看,我得到一个segfault错误每次我试着尊重时间after_number:也就是说,如果我打电话buildnumber时i指向字符串一样"111",我得到一个segfault它打印后"Advancing position".如果我把它当i个像字符串"+0.0"或者"abc()",我得到一个segfault它打印后"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));
Run Code Online (Sandbox Code Playgroud)
这实际上创建了一个char *变量,strtod可以放置结束指针,并将其地址传递给strtod.退出时,after_number将保持指向停止数值评估的结束字符的指针(希望,这将是指向提供的实际字符串结尾的指针,*after_number == '\0'.