Peter
Peter

Reputation: 45

function using fgets returns 0

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

Answers (1)

Achal
Achal

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

Related Questions