На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
Модераторы: JoeUser, Qraizer, Hsilgos
  
> динамическое выделение памяти для массива С-строк, realloc странно себя ведет, либо же я не умею им пользоваться
Добрый день.

Требуется помощь с увеличением памяти, выделенной для массива указателей на С-строку.

Задача такова: изначально выделяем немного памяти, а по ходу цикла понимаем, что памяти выделили мало, делаем до-выделение (через realloc()) и продолжаем пихать в наш массив указателей строчку.

Суть в том, что мы на этапе компиляции не знаем значение real_life_max (но для примера я взял 350).

ExpandedWrap disabled
    #include <stdio.h>
     
    void p2p()
    {
        const char *sample_str = "abc";
        const int initial_max = 50; // изначально предполагаем, что этого хватит
        const int real_life_max = 350; // жизнь показала, что нужно вот столько
     
        char **my_array = (char**)calloc(initial_max, sizeof(char)); // выделяем предполагаемый минимум
     
            // программа начинает работать в жесткой реальности
        for (int i = 0; i < real_life_max; i++)
        {
            if (i >= initial_max) // принимаем решение увеличивать выделенную память
            {
                char **tmp = (char**)realloc(my_array, sizeof(char) * 2); //
                my_array = tmp;
            }
            my_array[i] = (char*)malloc(8); // тут не уверен, надо ли выделять память на строку в массиве, на массив и так выделили calloc()-ом
            strcpy(my_array[i], sample_str);
        }
     
            //free();
    }
     
    int main(void)
    {
        p2p();
        return 0;
    }


По факту получаю ошибку
ExpandedWrap disabled
    Unhandled exception at 0x77910E23 (ntdll.dll) in tstmem.exe: 0xC0000374: Куча была повреждена (parameters: 0x7794E930).


windows 10, x64; MSVS 2017

Помогите, пожалуйста, с выделением памяти.
Травиан. Регистрируйтесь. Регистрация
Цитата barberan @
Помогите, пожалуйста, с выделением памяти.

На смотри. Чутка поправил твой пример:

ExpandedWrap disabled
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    void dump(char **array, size_t len) {
      for(size_t i=0; i<len; i++) printf("%03d : %s\n",i,*(array+i));
    }
     
    void p2p() {
      const char *sample_str = "abc";
      const size_t initial_max = 50; // изначально предполагаем, что этого хватит
      const size_t real_life_max = 350; // жизнь показала, что нужно вот столько
      size_t allocated = initial_max;
      char **my_array = (char**)calloc(allocated, sizeof(char*)); // выделяем предполагаемый минимум
      if (my_array != NULL) {
        // программа начинает работать в жесткой реальности
        for (size_t i = 0; i < real_life_max; i++) {
          if (i >= allocated) {
            // принимаем решение увеличивать выделенную память
            allocated = real_life_max;
            if ((my_array = realloc(my_array, allocated * sizeof(char*))) == NULL) {
              printf("realloc error!\n");
              exit(-1);
            }
          }
          my_array[i] = (char*)calloc(strlen(sample_str)+1,sizeof(char));
          if (my_array[i] == NULL) {
            printf("calloc-2 error!\n");
            exit(-1);
          }
          memmove(my_array[i], sample_str, strlen(sample_str)*sizeof(char));
        }
      } else {
        printf("calloc-1 error!\n");
        exit(-1);
      }
      // печатаем всю эту шляпу
      dump(my_array,allocated);
      // free
      for (size_t i = 0; i < real_life_max; i++) free(*(my_array+i));
      free(my_array);
    }
     
    int main(void) {
      p2p();
      return 0;
    }

Этот код в онлайн исполнении.
Мои программные ништякиhttp://majestio.info
Цитата JoeUser @
        if ((my_array = realloc(my_array, allocated * sizeof(char*))) == NULL) {
          printf("realloc error!\n");
          exit(-1);
        }

realloc может вернуть null, при этом старый указатель остаётся валидным и ему нужно сделать free.

ExpandedWrap disabled
    void p2p()
    {
        const char *sample_str = "abc";
        const int initial_max = 50; // изначально предполагаем, что этого хватит
        const int real_life_max = 350; // жизнь показала, что нужно вот столько
     
        size_t sz = initial_max;
        char **my_array = (char**)calloc(sz, sizeof(char *)); // выделяем предполагаемый минимум
     
            // программа начинает работать в жесткой реальности
        for (int i = 0; i < real_life_max; i++)
        {
            if (i >= sz) // принимаем решение увеличивать выделенную память
            {
                char **tmp = (char**)realloc(my_array, (sz *= 2) * sizeof(char *)); //
                if (!tmp)
                    break;
                my_array = tmp;
            }
     
            my_array[i] = (char *)malloc(strlen(sample_str) + 1);  
            strcpy(my_array[i], sample_str);
        }
     
        free(my_array);
    }
Цитата Олег М @
при этом старый указатель остаётся валидным и ему нужно сделать free.

На будущее учту. Но в этом коде - это лишнее.
Ибо идет закрытие проги и ось сама все вернет.

Добавлено
Олег М, твой free() из 25 строчки не освобождает память, выделенную под сами элементы.
Мои программные ништякиhttp://majestio.info
Всем спасибо, все работает!
Травиан. Регистрируйтесь. Регистрация
1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
0 пользователей:


Рейтинг@Mail.ru
[ Script Execution time: 0,5098 ]   [ 20 queries used ]   [ Generated: 18.03.19, 21:52 GMT ]