Reputation: 45
I am writing a small calculator, intended for an arduino, using RPN (reverse polish notation). Because I also want to make the code run on my x86 laptop, with setting some configuration parameters for my calculator program, I use functions like input_str
, input_int
and output_str
, so I can implement them differently for my laptop or the arduino.
Now in input_str
char *input_str(void) {
#if IS_IO_STDIO
char iobuf[IO_BUF_SIZE];
fgets(iobuf, IO_BUF_SIZE, stdin);
if (IS_DEBUG) { printf("1. iobuf: %s\n", iobuf); }
if (IS_DEBUG) { printf("2. iobuf ptr: %p\n", iobuf); }
return iobuf;
#elif IS_IO_SERIAL
// TODO: implement serial input str
#endif // IS_IO_STDIO
}
using fgets
, to get the user's input (for future calculations), 1. iobuf printout
properly prints out the string, typed in by the user, 2. iobuf ptr
properly prints out some char *
unequal to 0.
When I use the return value of input_str
in my ipo-loop:
int ipo_loop(int16_t *stack, int *sp) {
// TODO: implement real ipo loop
int is_exit = false;
char *iobuf;
while (!is_exit) {
iobuf = input_str();
if (IS_DEBUG) { printf("3. iobuf ptr: %p\n", iobuf); }
output_str(iobuf);
}
return 0;
}
3. iobuf ptr
suddenly shows, that iobuf
is now pointing to 0.
Why is iobuf
suddenly 0?
Is it some typecast issue from char[IO_BUF_SIZE]
to char *
?
Upvotes: 0
Views: 300
Reputation: 11921
In the below code
char *input_str(void) {
char iobuf[IO_BUF_SIZE];
fgets(iobuf, IO_BUF_SIZE, stdin);
/* some code */
return iobuf;
}
where you are returning local array iobuf
is causes undefined behavior. The char array iobuf
declared in input_str()
has local scope and its scope ends when control exits from this function.
If you could have compile your code with flags like -Wall
, -Wextra
etc, for e.g
gcc -Wall -Wextra -Werror -Wpedantic test.c
compiler could have warned you like
warning: address of stack memory associated with local variable 'iobuf' returned [-Wreturn-stack-address]
Above compiler warning tells everything about the issue & its readable.
Instead of returning local array, create the dynamic array & return it. For e.g
char *iobuf = malloc(IO_BUF_SIZE * sizeof(*iobuf));
/* @TODO if malloc was success i.e check return value of malloc */
After that scan the data using fgets()
as you did below.
fgets(iobuf, IO_BUF_SIZE, stdin);
And then retuen the dynamic array
return iobuf;
In calling API ipo_loop()
once you are done with dynamically returned array, don't forget to free
it to avoid memory leakage. for e.g
iobuf = input_str();
/* processing with iobuf.. here iobuf is dynamically returned array */
free(iobuf);
Upvotes: 4