На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: 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;
        }

      Этот код в онлайн исполнении.
        Цитата 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 строчки не освобождает память, выделенную под сами элементы.
            Всем спасибо, все работает!
            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
            0 пользователей:


            Рейтинг@Mail.ru
            [ Script execution time: 0,0246 ]   [ 16 queries used ]   [ Generated: 19.03.24, 09:56 GMT ]