Неверная запись после выделения памяти для члена структуры в массиве структур - PullRequest
0 голосов
/ 05 марта 2019

Мне нужно передать массив структур в функцию, и, насколько я понимаю, я должен выделить память для всего массива структур, а также для каждого отдельного члена структуры в каждой структуре внутри массива.

То, как я это сделал, приводит к недопустимой ошибке записи из valgrind (вызванной во второй строке внутри функции read_file). Что не так?

typedef struct test
{
    char *string1; 
    int num1; 
    int num2;
    char *string2;
} Test;

static void read_file(Test *test)
{
    test = (Test *)calloc(16, sizeof(test));
    test[0].string1 = (char *)calloc(strlen("hello") + 1, sizeof(char));
}

int main(void)
{
    int i = 0;
    Test test[16];

    for (i = 0; i < 16; i++)
    {
        memset(&test[i], 0, sizeof(test[i]));
        test[i] = (Test) { "", 0, 0, "" };
    }

    read_file(test);
    return 0;
}

PS: я знаю, что мне нужно освободить выделенную память, но сначала я хочу, чтобы приведенный выше код работал.

Ответы [ 2 ]

2 голосов
/ 05 марта 2019

Массиву test в main уже выделена память для него.

Затем вы передаете его в функцию read_file, поэтому вам не нужно выделять память для него снова.Удалите это:

test = (Test *)calloc(16, sizeof(test));

Кстати, вы, вероятно, намеревались sizeof(Test) (или, альтернативно, sizeof(*test)) там.sizeof(test) совпадает с sizeof(Test*), который почти наверняка меньше, чем sizeof(Test).

0 голосов
/ 05 марта 2019
Test *test

Переменная test внутри функции read_file является pointer для структуры Test.

sizeof(test)

Это равно размеру указателя .

test = (Test *)calloc(16, sizeof(test));

Это выделяет память для 16 указателя на Test структуру. Это не выделяет память для 16 структур, только для указателей на них.

test[0].string1 = 

недопустимо и происходит неопределенное поведение. Поскольку sizeof(test) намного меньше, чем sizeof(Test), недостаточно памяти для доступа к test0[].string1. Таким образом, это обращается к памяти «вне границ», и это обращается к недействительной / не выделенной области памяти. Когда вы пытаетесь написать в него (вы делаете задание), выражение является недопустимым и происходит неопределенное поведение. Valgrind правильно определяет это как «ошибку записи» - вы пытаетесь записать в память, которой вы не владеете.

...