Как я могу инициализировать массив указателей Struct внутри функции? - PullRequest
0 голосов
/ 13 мая 2018

У меня есть следующий test.h файл:

typedef struct node *Node;
struct node {
    const char *key;
    Node next;
};

typedef struct table_s *Table;
struct table_s {
    int n;
    Node *arrayOfNodes;
};

А также этот test.c файл:

Table new_table() {
    Table thisTable = malloc(sizeof(Table));
    thisTable->n = 2;
    thisTable->arrayOfNodes = malloc(thisTable->n*sizeof(Node));

    //this line is inserted here so I can check that calling malloc() like this actuallt work
    Node *array = malloc(thisTable->n*sizeof(Node)); 

    return thisTable;
}

int main() {

    Table myTable = new_table();

return 0;
}

Программа компилируется и работает, но valgrind.log указывает тамошибки:

==8275== Invalid write of size 8
==8275==    at 0x40056E: new_table (test.c:8)
==8275==    by 0x40043A: main (test.c:18)
==8275==  Address 0x5204048 is 0 bytes after a block of size 8 alloc'd
==8275==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8275==    by 0x40055A: new_table (test.c:6)
==8275==    by 0x40043A: main (test.c:18)

Почему вызов malloc () в строке 11 работает нормально, а в строке 8 вызывает эти ошибки?Это заставляет мою большую версию этой программы не работать с большими записями (когда n становится больше).

1 Ответ

0 голосов
/ 13 мая 2018

«Размер 8» - подсказка: это размер указателя в вашей системе. Вы хотели выделить объект, а не указатель.

sizeof(Node) совпадает с sizeof(struct node *), а sizeof(Table) имеет аналогичную проблему.

Это сработало бы, если бы вы написали что-то вроде этого:

typedef struct table_s Table, *TablePtr;
...
TablePtr thisTable = malloc(sizeof(Table));

Если вы настаиваете на типах, как они, вы можете просто использовать следующую общую malloc идиому:

// General form:
//   T *p = malloc(sizeof *p);
// or:
//   T *p = malloc(N * sizeof *p);
Table this_table = malloc(sizeof *this_table);
...
this_table->arrayOfNodes = malloc(thisTable->n * sizeof *this_table->arrayOfNodes);

Почему вызов malloc() в строке 11 работает нормально, но в строке 8 вызывает эту ошибку?

Поскольку вы выделяете Table (размер = 8), попытайтесь получить к нему доступ, как если бы это было struct table_s (размер = 16). Ваше объявление array в порядке, но перед этим вы пытаетесь записать указатель, возвращаемый malloc в this_table->arrayOfNodes, который находится со смещением 8 в структуре (то есть смещение 0 равно n, а смещение 8 равно arrayOfNodes). Короче говоря, вы пытаетесь записать вне выделенной памяти: вы выделили только 8 байтов, но вы пишете после первых 8 байтов структуры.

...