Попытка изучить правильную обработку памяти в C - malloc, realloc и free - PullRequest
1 голос
/ 26 февраля 2012

Итак, у меня два (надеюсь, быстрых) вопроса.Я думаю, что у меня есть навык использования malloc для экономии места для данных, но realloc вызывает проблемы.В приведенном ниже коде у меня есть массив из 8 символьных указателей, который - если он заполнится - я пытаюсь расширить, чтобы иметь еще один 8 символьных указателей (а затем еще 8 и т. Д.),Realloc делает это в первый раз (то есть расширяет массив один раз), но после этого я получаю следующую ошибку:

*** glibc detected *** ./a.out: realloc(): invalid next size:

Насколько я могу судить, ничего не меняется.Почему realloc работает с массивом из 8, а не с массивом из 16?

И мой второй вопрос касается утечек памяти.Я до сих пор не уверен, что мне нужно бесплатно в программе.Другие советовали мне, что inputcpy должен быть освобожден.Это все здесь?Кроме того, в какой момент в программе я хочу освободить его?

#define DEBUG 1

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

char ** getArgs( char *input,  char **args, int ct);
char ** args;

int main(int argc, char* argv[]) {
  char input[]="echo arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 arg11 arg12 arg13";
  char inputcpy[strlen(input)];
  strcpy(inputcpy, input);
  char * prog=strtok(input, " ");

  /*Saving space for an array of 8 strings*/
  args=( char **) calloc(8, sizeof( char *));  

  getArgs(inputcpy, args, 1);

  if(DEBUG) {
    printf("arg address after: %p\n", args);
  }

  int q;
  int pid=fork();
  if (pid==0) {
    execvp(prog, args); 
    return 0;
  }
  else {
    int status=0;
    wait(&status);
  }
}

char ** getArgs( char *input,  char **args, int ct) {
  int adj=(ct-1)*8;//if we recurse, this ensures correct indexes are used
  char *inputcpy=malloc(strlen(input));
  strcpy(inputcpy, input);

  /*Initialize indexes/Prepare for copying*/
  int i; 
  if(ct==1) {
    i=1;
    args[0]=" "; //quick hack to ensure all args are used by exec()
  }
  else
    i=0;

  /**Actually do the copying now**/
  char *temp=strtok(NULL, " ");
  args[adj+i++]=temp;
  while (temp != NULL && i<8) {
    temp=strtok(NULL, " ");
    args[adj+i++]=temp;
  }   

  /*If there are more args than we have room for*/
  if(i>=8){
    /*Increase the array to store 8 more strings*/
    args= (char **) realloc(args, sizeof(args)+8*sizeof(char *) );
    getArgs(inputcpy, args, (++ct) );
  }   

  return NULL;
}

Ответы [ 2 ]

2 голосов
/ 26 февраля 2012
 char *inputcpy=malloc(strlen(input));
 strcpy(inputcpy, input);

вы не выделяете достаточно места для вашей строки, должно быть: malloc(strlen(input) + 1);

То же самое здесь:

 char inputcpy[strlen(input)];
 strcpy(inputcpy, input);

Строка - это последовательность символов, оканчивающаяся и включающаянулевой символ, а длина строки - это количество символов, предшествующих нулевым символам.

Также вы используете realloc неправильно:

args= (char **) realloc(args, sizeof(args)+8*sizeof(char *) );

Возможна утечка памяти вэто использование.

Что касается free, то, что вы должны сделать, просто: каждый malloc должен иметь соответствующий free.

0 голосов
/ 27 февраля 2012

Я отвечу на ваш последний вопрос, который был: Кроме того, в какой момент в программе я хочу освободить его?

Что ж, рекомендуется освободить его прямо перед ответной стадиейфункция, которая называется malloc.Если вы сделаете это, вам не придется беспокоиться о какой-либо утечке памяти.

Однако вызывающая функция, в вашем случае main, может также вызывать free (), когда ваша функция getArgs () завершена ивозвращает управление на главную.Это потому, что можно использовать другую переменную-указатель с free ();вам просто нужно убедиться, что новый указатель хранит тот же адрес.

...