0

I been trying to figure out why Valgrind reports unreachable memory and the buffer gets corrupted when i don't return the pointer (case 2) .

As i understand it i give read_input a pointer and it uses it. If realloc is caused i get a new pointer and replace the old one, so the pointer of input_buffer in main,and wherever there is that pointer it should have that new pointer, but it doesn't.

Is it maybe that i am passing literally the address ? So the input_buffer in main has the old address as it was never changed? (My C is a bit rusty)

Is there a way to keep the input_buffer "updated" without returning the value like case 1 ? thus being able to write code like case 2 ? (without having the buffer global/static)

#include "dev_utils.h"
#include "promt.h"
#include "sh_input.h"

int main(int argc, char *argv[]) {

  // char *input_buff = (char *)malloc(CMD_BUFF * sizeof(char));
  char *input_buff = (char *)malloc(1024 * sizeof(char));
  if (!input_buff) {
    fprintf(stderr, "Memory allocation failed at %s:%d! Exiting.\n",
            "cs345sh.c", 8);
    exit(1);
  };

  while (1) {
    put_promt();
// 1.  input_buff = read_input(input_buff);
// 2.  read_input(input_buff);
    parse_input(input_buff);
  }
  free(input_buff);

  return 0;
}
#include "sh_input.h"
#include "dev_utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *read_input(char *input_buff) {

  unsigned int input_buffer_size = CMD_BUFF;
  unsigned int input_index = 0;
  char input;

  while(1) {
    input = getchar();
    if (input_index >= input_buffer_size) {
      input_buffer_size += CMD_BUFF;
      char *new_buff;
      new_buff = realloc(input_buff, input_buffer_size);
      if (!new_buff) {
        fprintf(stdout, "Memory allocation failed at %s:%d! Exiting.\n",
                "sh_input.c", 17);
        exit(1);
      };
      input_buff = new_buff;
    }

    if (input == EOF || input == '\n') {
      input_buff[input_index] = '\0';
      return input_buff;
    } else {
      input_buff[input_index] = input;
    }
    ++input_index;
  }
 // 1. return input_buff;
}
void parse_input(char *input) {
  if (strcmp(input, "exit") == 0) {
    free(input);
    exit(EXIT_SUCCESS);
  }
  printf("%s\n", input);
}

Lampros
  • 321
  • 3
  • 10
  • 2
    You'd need to have a `char**` argument and call it like `read_input(&input_buff);` See: https://stackoverflow.com/questions/766893/how-do-i-modify-a-pointer-that-has-been-passed-into-a-function-in-c – UnholySheep Oct 10 '22 at 21:41
  • 2
    You pass the old `input_buff` to `read_input`, but if `read_input` calls `realloc`, you aren't returning the new points back to `main`. So `main` attempts to free the old buffer, which is a bug (and undefined behavior). – Tom Karzes Oct 10 '22 at 21:49
  • 1
    Read the man page for `realloc()` and figure out how to use it (initially with `input_buff` being NULL)... You don't need to `malloc()` in main() at all... And, yes, you need to either pass the address of input_buff from main() to the function, OR capture the returned value that the function may have had to alter. (`realloc( NULL, ...` acts just like `malloc(...`) – Fe2O3 Oct 10 '22 at 23:04
  • I did as @UnholySheep said but i get a Seg fault at `*input_buff[input_index] = input;` ... – Lampros Oct 11 '22 at 07:56
  • Solved it ,wrong syntax . `(*input_buff)[input_index] = input; ` – Lampros Oct 11 '22 at 09:58

1 Answers1

2

Function arguments are passed by value in C. The input_buff parameter is a different object than the variable that you pass into the function when you call it (they have different memory addresses, even though the pointer value stored at these two addresses is initially the same). Thus, updating the parameter variable has no effect on the variable in the caller function.

So the caller function must take care of updating its own variable, which you can achieve by returning the new pointer, or as @UnholySheep has already pointed out in the comments to your question, you could instead pass a pointer to the variable to overwrite it from within the read_input function.

JayK
  • 3,006
  • 1
  • 20
  • 26