Динамически выделить массив структуры, содержащий динамически размещенный массив - PullRequest
1 голос
/ 11 ноября 2019

Я пытаюсь прочитать значения настроек из файла XML и, чтобы упростить задачу, я настроил структуру, содержащую каждое значение. Одним из них является массив структур. Затем я инициализирую структуру как массив. Во время выполнения кода я иногда получаю плавный запуск, иногда сбои и иногда прерывание (malloc: *** error for object: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug Abort trap: 6). Я предполагаю, что это неопределенное поведение.

Возможно, у меня есть подсказка о том, почему это происходит, но я не смог получить никаких подтверждений, хотя я проводил тщательное исследование. По моему мнению, это вызвано выделением пространства для массива структуры, выделяющего достаточно памяти, чтобы содержать структуру с некоторыми значениями плюс пустой массив структур. Затем я выделяю память для второго массива структуры, поэтому меняю пространство, необходимое для первого массива структур.

Это объявление структур:

struct Delegate {

  int warnings;

  gchar *name;

};

struct Staff {

  gchar *president;
  gchar *vice;
  gchar *mod;

};

struct Committee {

  int n_delegate;

  gchar *name;
  gchar *topics[2];

  struct Delegate *delegates;
  struct Staff staff;


};

А воткод, который я пытаюсь запустить:

static void load_prop() {

  xmlDocPtr doc;
  xmlNodePtr node;
  xmlNodePtr subnode;
  xmlNodePtr subsubnode;
  xmlNodePtr subsubsubnode;
  xmlChar *cnumber;

  doc = xmlParseFile("/Users/username/Documents/Obermun/DebateProgram/res/xml/property.xml");
  node = xmlDocGetRootElement(doc);

  edition = (char *) xmlGetProp(node, (const xmlChar *) "edition");

  int const index = atoi((const char*)(xmlGetProp(node, (const xmlChar *) "committees")));
  committees = (Committee *) malloc(sizeof(Committee)*index);

  subnode = node -> xmlChildrenNode;
  int i = 0;
  int t = 0;
  int d = 0;

  while(subnode != NULL) {

    if(!xmlStrcmp(subnode -> name, (const xmlChar *) "committee")) {

      committees[i].name = (char *) xmlGetProp(subnode, (const xmlChar *) "name");
      committees[i].n_delegate = atoi((const char*) xmlGetProp(subnode, (const xmlChar *) "delegates"));
      committees[i].delegates = (Delegate *) malloc(sizeof(Delegate)*committees[i].n_delegate);

      subsubnode = subnode -> xmlChildrenNode;

      while(subsubnode != NULL) {

        if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "topic")) {

          committees[i].topics[t] = (char *) xmlNodeListGetString(doc, subsubnode -> xmlChildrenNode, 1);
          t++;

        }

        else if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "delegate")) {

          committees[i].delegates[d].warnings = atoi((const char*) xmlGetProp(subsubnode, (const xmlChar *) "warnings"));
          committees[i].delegates[d].name = (char *) xmlNodeListGetString(doc, subsubnode -> xmlChildrenNode, 1);
          d++;

        }

        else if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "staff")) {

          subsubsubnode = subsubnode -> xmlChildrenNode;

          while(subsubsubnode != NULL) {

            if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "president")) {

              committees[i].staff.president = (char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1);

            }

            if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "vice")) {

              committees[i].staff.vice = (char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1);

            }

            if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "mod")) {

              committees[i].staff.mod = (char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1);

            }

            subsubsubnode = subsubsubnode -> next;

          }

        }

        subsubnode = subsubnode -> next;

      }

      i++;

    }

    subnode = subnode -> next;

  }

}

Попытка отладки кода с помощью gdb Я получаю эту обратную трассировку:

Thread 2 received signal SIGABRT, Aborted.
0x00007fff7353ab66 in ?? () from /usr/lib/system/libsystem_kernel.dylib
(gdb) bt
#0  0x00007fff7353ab66 in ?? () from /usr/lib/system/libsystem_kernel.dylib
#1  0x00007fff73705080 in pthread_kill () from /usr/lib/system/libsystem_pthread.dylib
#2  0x00007fff734961ae in abort () from /usr/lib/system/libsystem_c.dylib
#3  0x0000003000000010 in ?? ()
#4  0x00007ffeffffffdf in ?? ()
#5  0xffffffff0160f658 in ?? ()
#6  0x000000010160f658 in ?? ()
#7  0x00007ffeefbff5f0 in ?? ()
#8  0x00007fff7359fb58 in szone_error () from /usr/lib/system/libsystem_malloc.dylib
Backtrace stopped: frame did not save the PC

1 Ответ

0 голосов
/ 11 ноября 2019

Как отметил @nwellnhof в комментариях, проблема этого фрагмента кода в том, что переменные d и t, которые я использую для хранения значений делегатов и тем, никогда не сбрасываются в 0, поэтому при каждом цикле они растутпытается сохранить значения в нераспределенном пространстве памяти, что приводит к неопределенному поведению.

Правильный код следующий:

static void load_prop() {

  xmlDocPtr doc;
  xmlNodePtr node;
  xmlNodePtr subnode;
  xmlNodePtr subsubnode;
  xmlNodePtr subsubsubnode;
  xmlChar *cnumber;

  doc = xmlParseFile("/Users/username/Documents/Obermun/DebateProgram/res/xml/property.xml");
  node = xmlDocGetRootElement(doc);

  edition = (char *) xmlGetProp(node, (const xmlChar *) "edition");

  int const index = atoi((const char*)(xmlGetProp(node, (const xmlChar *) "committees")));
  committees = (struct Committee *) malloc(sizeof(struct Committee)*index);

  subnode = node -> xmlChildrenNode;
  int i = 0;
  int t = 0;
  int d = 0;

  while(subnode != NULL) {

    if(!xmlStrcmp(subnode -> name, (const xmlChar *) "committee")) {

      committees[i].name = strdup((char *) xmlGetProp(subnode, (const xmlChar *) "name"));
      committees[i].n_delegate = atoi((const char*) xmlGetProp(subnode, (const xmlChar *) "delegates"));
      committees[i].delegates = (struct Delegate *) malloc(sizeof(struct Delegate)*committees[i].n_delegate);

      subsubnode = subnode -> xmlChildrenNode;

      t = 0;
      d = 0;

      while(subsubnode != NULL) {

        if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "topic")) {

          committees[i].topics[t] = strdup((char *) xmlNodeListGetString(doc, subsubnode -> xmlChildrenNode, 1));
          t++;

        }

        else if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "delegate")) {

          committees[i].delegates[d].warnings = atoi((const char*) xmlGetProp(subsubnode, (const xmlChar *) "warnings"));
          committees[i].delegates[d].name = strdup((char *) xmlNodeListGetString(doc, subsubnode -> xmlChildrenNode, 1));
          d++;

        }

        else if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "staff")) {

          subsubsubnode = subsubnode -> xmlChildrenNode;

          while(subsubsubnode != NULL) {

            if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "president")) {

              committees[i].staff.president = strdup((char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1));

            }

            if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "vice")) {

              committees[i].staff.vice = strdup((char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1));

            }

            if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "mod")) {

              committees[i].staff.mod = strdup((char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1));

            }

            subsubsubnode = subsubsubnode -> next;

          }

        }

        subsubnode = subsubnode -> next;

      }

      i++;

    }

    subnode = subnode -> next;

  }

}

Уведомление t и d существоустановите на 0 перед каждым циклом.

...