Странные вещи случаются после использования std :: strtod

Вот небольшая лямбда-функция, которую я использую в качестве вспомогательной функции в коде моего лексического анализатора:

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, В первой строке я инициализирую новый, передавая его конструктору нулевой указатель для значения (так как мы все еще должны его создать), значение enum token_type (number потому что этот токен относится к этому типу), и текущая строка, которую мы записали в лямбду.

i указатель типа const char* который указывает на текущего персонажа, которого мы исследуем. Когда мы вызываем эту лямбда-функцию, это гарантирует, что она будет указывать на печатный символ.

printfs для целей отладки;

Так что я пытаюсь сделать это: создать новый 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? Что я делаю неправильно?

0

Решение

Вы определили 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',

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]