Reputation: 9509
I want to store a string in memory and read it later:
$$->desc.constant->base.id = (char*)malloc(200);
sprintf($$->desc.constant->base.id, "%f", $1);
printf("->%s\n", $$->desc.constant->base.id); //LINE A
printf("->%i\n", $$->desc.constant); //LINE B
//SOME OTHER CODE
//Then, later on in a function call:
printf("%i", expr->desc.constant); // LINE D
printf("%s", expr->desc.constant->base.id); // LINE C
Although Line B and Line D show the same address, the printf in Line C fails with a Segmentation fault. What am I missing?
Any help would really be appreciated!
Upvotes: 3
Views: 600
Reputation: 753455
Given that the program is producing a segmentation fault, I think the problem is most likely that the structure designated (pointed to) by expr->desc.constant
has been reused since the space was allocated, or possibly the space was never really allocated at all.
The code exhibits various venial sins, such as using sprintf()
instead of snprintf()
, and gratuitously allocating 200 bytes for the string representation of a floating point number. (You are very unlikely to need that much space; if you do, you should most probably allow for at least 100 more digits than you have, since the exponent range for floating point numbers is usually +/-308, and the only reason you'd need 200 characters is to allow for incredibly large or incredibly tiny numbers.)
You have shown that $$->desc.constant
points to the same place, but you have not shown how that space is allocated. You then allocate the string space in $$->desc.constant->base.id
, without clearly allocating the space for base
.
Upvotes: 0
Reputation: 414079
malloc
's return value.sprintf
-> snprintf
"%f"
-> "%.*g"
Here's an example:
/** $ gcc print_number.c -o print_number */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
const char* number_format = "%.*g";
const int ndigits = 15;
assert(ndigits > 0);
const int maxlen = ndigits + 8 /* -0.e+001, Infinity */ + 1 /* '\0' */;
char *str = malloc(maxlen);
if (str == NULL) {
fprintf(stderr, "error: malloc\n");
exit(1);
}
double number = 12345678901234567890.123456789012345678901234567890;
/** `number = 0/0` crashes the program */;
printf("number: %f\t", number);
int len_wouldbe = snprintf(str, maxlen, number_format, ndigits, number);
assert(len_wouldbe < maxlen);
printf("%s\n", str);
return 0;
}
Output:
number: 12345678901234567000.000000 1.23456789012346e+19
Upvotes: 1
Reputation: 135245
Maybe between the time of the two pieces of code you have since free
d the string?
$$->desc.constant->base.id = (char*)malloc(200);
sprintf($$->desc.constant->base.id, "%f", $1);
printf("->%s\n", $$->desc.constant->base.id); //LINE A
printf("->%i\n", $$->desc.constant); //LINE B
//SOME OTHER CODE
// which happens to do
free($$->desc.constant->base.id);
printf("%i", expr->desc.constant); // LINE D
printf("%s", expr->desc.constant->base.id); // crash
Upvotes: 0
Reputation: 506837
printf("->%i\n", $$->desc.constant); //LINE B
That is invalid. As you show the line prior to it that constant
is actually a pointer, you cannot treat it as if it were of type int
. They don't necassarily have the same sizeof and alignment. Use the format used for void*
. It will output memory addresses properly:
printf("->%p\n", (void*)$$->desc.constant); //LINE B
Upvotes: 9