LINUX.ORG.RU

История изменений

Исправление MOPKOBKA, (текущая версия) :

Я не предлагал все выделять на стеке, это было бы странно. Давай покажу на примере «преобразования».

Была сложная функция с несколькими массивами

int work(void) {
    // Для начала выделяется пару элементов для массива
    // потом их надо будет растить с помощью realloc
    char *str1 = malloc(...); 
    int *arr1 = malloc(...);
    int *arr2 = malloc(...);
    int *arr3 = malloc(...);
    // Много проверок что все выделили

    // Так как изначально элементов выделили мало
    // нужно перераспределять память и добавить еще проверки
    arr1 = realloc(...);
    arr2 = realloc(...);

    // Надо следить за всеми выходами
    if (x < 2) {
      free(...); free(...);
      return 10;
    }

    // И не забыть все правильно очистить
    free(...);
    return 0;
}
Эту же функцию можно преобразовать в такую:
struct data {
  char str[PATH_MAX];
  int arr1[9999], arr2[100], arr3[32];
  int arr1_len, arr2_len, arr3_len;
};

int work(struct data *data) {
    // Ничего не выделяется, работа идет с data
    // Размер уже выделен достаточный для работы
    // но если не хватит то придется выдать ошибку
    // так что лучше расчитать заранее
    if (x < 2) {
      // Не надо заботится что может что то утечь
      return 10;
    }
    // И очистка на стороне data
    return 0;
}

int main() {
  // Один раз выделили
  struct data *d = malloc(...);
  data_initialize(d); // Ставим len по нулям
  work(d);  // Работаем не отвлекаясь на выделение/освобождение
  work2(d);
  work3(d);
  free(d); 
}

Если все функции написаны по второму примеру, то где то наверху, возможно только в main ты выделяешь разово массивы, а потом просто с ними работаешь, не трогая malloc/realloc. Код упрощается, скорость возрастает.

Исправление MOPKOBKA, :

Я не предлагал все выделять на стеке, это было бы странно. Давай покажу на примере «преобразования».

Была сложная функция с несколькими массивами

int work(void) {
    // Для начала выделяется пару элементов для массива
    // потом их надо будет растить с помощью realloc
    char *str1 = malloc(...); 
    int *arr1 = malloc(...);
    int *arr2 = malloc(...);
    int *arr3 = malloc(...);
    // Много проверок что все выделили

    // Так как изначально элементов выделили мало
    // нужно перераспределять память и добавить еще проверки
    arr1 = realloc(...);
    arr2 = realloc(...);

    // Надо следить за всеми выходами
    if (x < 2) {
      free(...); free(...);
      return 10;
    }

    // И не забыть все правильно очистить
    free(...);
    return 0;
}
Эту же функцию можно преобразовать в такую:
struct data {
  char str[PATH_MAX];
  int arr1[9999], arr2[100], arr3[32];
  int arr1_len, arr2_len, arr3_len;
};

int work(struct data *data) {
    // Ничего не выделяется, работа идет с data
    // Размер уже выделен достаточный для работы
    // но если не хватит то придется выдать ошибку
    // так что лучше расчитать заранее
    if (x < 2) {
      // Не надо заботится что может что то утечь
      return 10;
    }
    // И очистка на стороне data
    return 0;
}

int main() {
  // Один раз выделили
  struct data *d = malloc(...);
  data_initialize(d); // Ставим len по нулям
  work(d);  // Работаем не отвлекаясь на выделение/освобождение
  work2(d);
  work3(d);
  free(d); 
}

Исходная версия MOPKOBKA, :

Я не предлагал все выделять на стеке, это было бы странно. Давай покажу на примере «преобразования».

Была сложная функция с несколькими массивами

int work(void) {
    // Для начала выделяется пару элементов для массива
    // потом их надо будет растить с помощью realloc
    char *str1 = malloc(...); 
    int *arr1 = malloc(...);
    int *arr2 = malloc(...);
    int *arr3 = malloc(...);
    // Много проверок что все выделили

    // Так как изначально элементов выделили мало
    // нужно перераспределять память и добавить еще проверки
    arr1 = realloc(...);
    arr2 = realloc(...);

    // Надо следить за всеми выходами
    if (x < 2) {
      free(...); free(...);
      return 10;
    }

    // И не забыть все правильно очистить
    free(...);
    return 0;
}
Эту же функцию можно преобразовать в такую:
struct data {
  char str[PATH_MAX];
  int arr1[9999], arr2[100], arr3[32];
  int arr1_len, arr2_len, arr3_len;
};

void work(struct data *data) {
    // Ничего не выделяется, работа идет с data
    // Размер уже выделен достаточный для работы
    // но если не хватит то придется выдать ошибку
    // так что лучше расчитать заранее
    if (x < 2) {
      // Не надо заботится что может что то утечь
      return 10;
    }
    // И очистка на стороне data
    return 0;
}

int main() {
  // Один раз выделили
  struct data *d = malloc(...);
  data_initialize(d); // Ставим len по нулям
  work(d);  // Работаем не отвлекаясь на выделение/освобождение
  work2(d);
  work3(d);
  free(d); 
}