malloc внутри функции/вызов по ссылке/valgrind

Я не очень хорошо разбираюсь в C, поэтому у меня проблема с valgrind.

Я хочу прочитать ввод из командной строки.

Если я попробую так, то все будет хорошо.

//call the function
char *command = getUserInput();


//function
char *getUserInput()
{ 
  char *buffer = NULL;
  char *temp = NULL;
  unsigned int count = 0;
  unsigned int lenght = 10;
  char character = 0;

  buffer = malloc((lenght+1)*sizeof(char));
  if(buffer == NULL)
  {
    // printf(ERROR_OUT_OF_MEM);
    // return EXIT_OUT_OF_MEM;
  }

  while((character = getchar()) != '\n')
  {
    if(count == lenght)
    {
      lenght += 10;
      temp = realloc(buffer,lenght*sizeof(char));
      if(temp != NULL)
        {
          buffer = temp;
        }
      else
        {
          free (buffer);
          // printf(ERROR_OUT_OF_MEM);
          // return EXIT_OUT_OF_MEM; 
        }
    }

    buffer[count] = character;
    count++;

  }
  buffer[count] = '\0';

  return buffer;
}

Но я не могу получить возвращаемое значение ошибки.

Если я попробую это сделать с помощью вызова по ссылке, я получу какую-то ошибку valgrind, которую я не понимаю. И я знаю, что в этом примере вызова функции я не запрашиваю возвращаемое значение.

//call function
char *command = NULL;
getUserInput(command);

//function
int getUserInput(char *name)
{ 
  char *temp = NULL;
  unsigned int count = 0;
  unsigned int lenght = 10;
  char character = 0;

  name = malloc((lenght+1)*sizeof(char));
  checkMemory(name);

  while((character = getchar()) != '\n')
  {
    if(count == lenght)
    {
      lenght += 10;
      temp = realloc(name,lenght*sizeof(char));
      if(temp != NULL)
        {
          name = temp;
        }
      else
        {
          free (name);
          printf(ERROR_OUT_OF_MEMORY_MESSAGE);
          return ERROR_OUT_OF_MEMORY; 
        }
    }

    name[count] = character;
    count++;

  }
  name[count] = '\0';

  return RETURN_SUCCESS;
}

Строка обработчика команд 1199: if (strcmp(command, "thing_to_compare") == 0)

Валгринд:

==23886== Use of uninitialised value of size 4
==23886==    at 0x40256BB: strcmp (mc_replace_strmem.c:426)
==23886==    by 0x8049B39: commandHandler (assa.c:1199)
==23886==    by 0x8049D6C: main (assa.c:1295)
==23886==  Uninitialised value was created by a stack allocation
==23886==    at 0x8049B00: commandHandler (assa.c:1189)
==23886== 
==23886== Invalid read of size 1
==23886==    at 0x40256BB: strcmp (mc_replace_strmem.c:426)
==23886==    by 0x8049B39: commandHandler (assa.c:1199)
==23886==    by 0x8049D6C: main (assa.c:1295)
==23886==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

Я совершенно не знаю, где проблема.

с уважением Филипп


person phiob    schedule 24.01.2014    source источник
comment
Пишет, что проблема в функции под названием commandHandler. Как вы ожидаете, что мы скажем что-то разумное об этой функции, если вы нам ее не покажете?   -  person Jens Gustedt    schedule 24.01.2014
comment
Извините, я забыл командуHandler. Я отредактировал сообщение.   -  person phiob    schedule 24.01.2014
comment
command равно NULL, это ошибка. В C нет ничего похожего на вызов по ссылке. Вы отправляете значение команды в функцию, и если оно там изменяется, то это локальная копия, которая изменяется, а не исходная переменная.   -  person Marian    schedule 24.01.2014


Ответы (1)


getUserInput не может изменить значение command, так как все функции в C передаются по значению. Поэтому, когда вы получаете все свои strcmp функции, вы разыменовываете этот указатель NULL, вызывая всевозможные плохие вещи.

Если вы хотите, чтобы getUserInput могла изменять значение command, вы должны передать адрес command в функцию (что означает, что функция должна принимать аргумент char**).

person tabstop    schedule 24.01.2014
comment
Спасибо, так что теперь я должен передать значение вот так? getUserInput(&command); а в функции int getUserInput(char **name)? Я не понимаю, как получить доступ к name внутри функции. Изменить каждые name на *name? Если я сделаю это, я получу ошибку сегментации. - person phiob; 24.01.2014
comment
Когда вы доберетесь до назначения отдельных персонажей, вам придется сделать что-то вроде (*name)[count], чтобы сохранить порядок операций. - person tabstop; 24.01.2014