user6245072 user6245072 - 1 year ago 37
C++ Question

Strange things happen after using std::strtod

Here's a small lambda function I use as an helper function in the code for my lexical analyzer:

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;

return new_number;

Here's a little background:
is a class with an attribute
of type
, an attribute
of type
, and an attribute
of a custom enum
. In the first line I initialize a new one passing to its constructor a null pointer for the value (since we still have to create it), a value of the enum
because this token is of that type), and the current line we captured in the lambda.

is a pointer of type
const char*
which points to the current characyer we're examining. When we call this lambda function, it's guaranteed that it will point to a printable character.

s are for debugging purpose;

So what I am trying to do is: create a new
of internal type
; ask
if we can build a number from the current position; then check if
returned a non-zero value, in which case we store that value in the new
, advance the position of the character we're pointing to to the character directly after the number, and return the

returned a zero value instead, we must doublecheck if the zero is because an actual 0 was found, or if instead no number could be built. So we check if the pointer to the character after the number points to the same character as the current positions: if it's true, it means that
didn't advance that pointer and it means no number at all was found (and we delete the allocated values and return a null pointer to signal that). Otherwise, it means that a 0 was found and so we store it, advance, and return.

The problem is, I get a Segfault error literally every time I try to deference
: that is, if I call
points to a string like
, I get a segfault after it prints
"Advancing position"
. And if I call it when
points to a string like
, I get a segfault after it prints
"Value was 0, comparing position to after number"

Why is it? What happens to the pointer pointed to by
? What am I doing wrong?

Answer Source

You've defined after_number as a pointer to a character pointer and then used that directly, when it doesn't actually point to anything useful.

The problem with that is that you're basically telling strtod not to actually store the end pointer (because you've provided nullptr as the address to store it in), then you go ahead and try to dereference it anyway - it will still be nullptr and you'll therefore get undefined behaviour.

The correct way to do it is as follows:

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

This actually creates a char * variable into which strtod can place the end pointer, and passes the address of it to strtod. Upon exit, after_number will hold the pointer to the end character that stopped the numeric evaluation (hopefully, that will be a pointer to the end of the actual string supplied, *after_number == '\0'.