Выделение памяти для структуры указателя, которая имеет члены-указатели - PullRequest
0 голосов
/ 24 мая 2018

Я пытаюсь читать и печатать, используя указатель структуры, который имеет члены-указатели.Поэтому я пытаюсь прочитать и распечатать массив указателей с двойной структурой.Я попытался выполнить следующее, но оно выдает мне сообщение об ошибке «Место записи нарушения доступа (где-то в памяти)»

Как я могу динамически выделить память для этого?

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <stdio.h>
#include<string.h>
#include <stdlib.h>

typedef struct template{
char *name;
int  *birthdate;
int *phoneNum;

} detailsOf;

void inputValue(detailsOf **person, int maxSize);

int main() {

detailsOf **person;
int maxSize = 0, menu = 0;

printf("Max:");
scanf("%d", &maxSize);


person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));
if (person == NULL) {
    printf("Failed to allocate");
    exit(0);
}
for (int i = 0; i < maxSize; i++) {
    person[i]->name = (char *)calloc(21, sizeof(char ));
    person[i]->birthdate = (int *)calloc(8, sizeof(int ));
    person[i]->phoneNum = (int *)calloc(16, sizeof(int ));
}

inputValue(person, maxSize);

for (int i = 0; i < maxSize; i++) {
    free(person[i]);
    for (int j = 0; j < 21; j++) {
        free(person[i]->name[j]);
    }
    for (int j = 0; j < 15; j++) {
        free(person[i]->phoneNum[j]);
    }
    for (int j = 0; j < 8; j++) {
        free(person[i]->birthdate[j]);
    }
}
    return 0;
}
void inputValue(detailsOf **person, int maxSize) {
    for (int i = 0; i < maxSize; i++) {
        printf("Name of %d", i + 1);
        scanf("%s", person[i]->name);
          for (int j = 0; j < 8; j++) {
             printf("Birth %d:", i + 1);
             scanf("%d", person[i]->birthdate[j]);
     } 
     for (int k = 0; k < 8; k++) {
         printf("Phone %d:", i + 1);
         scanf("%d", person[i]->phoneNum[k]);
      }
   }
    printf("SUCCESS\n");
}

Ответы [ 3 ]

0 голосов
/ 24 мая 2018
person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));

должно быть

person = malloc(maxSize * sizeof(detailsOf *));

Затем эта выделенная память содержит указатели на detailsOf, но вы никогда не выделяете память для каждого detailsOf

for(int i=0; i<maxSize; i++)
{
   person[i]=malloc(sizeof(detailsOf));
}

Также вашосвобождение памяти должно быть

for (int i = 0; i < maxSize; i++)
{
    free(person[i]->name);
    free(person[i]->phoneNum);
    free(person[i]->birthdate);
    free(person[i]);
}
free(person);

Помните, что при освобождении просто сопоставьте свои free вызовы с malloc вызовами.

0 голосов
/ 24 мая 2018
person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));

Это выделяет массив двойных указателей для типа detailsOf с размером массива как maxSize.

sizeof(detailsOf**) - это размер адреса, он не дает вам размерваш пользовательский тип данных detailsOf.

Кроме того, двойной указатель означает, что это адресная ячейка, в которой будет храниться адрес другого указателя, который указывает на ячейку памяти detailsOf

/* if you want to use double pointer then */
detailsOf **dptr;  // two dimensional array of detailsOf */
detailsOf *sptr;   /* one dimentional array of detailsOf */

/* This allocates the memory for storing 3 detailsOf struct data */
sptr = malloc(3 * sizeof(detailsOf)); 
dptr = &sptr;

/* Now to access double ptr */
for (int i = 0; i < 3; ++i) {
    dptr[0][i].birthdate = malloc(3 * sizeof(int));
}

for (int i = 0; i < 3; ++i) {
    dptr[0][i].birthdate[0] = i; 
    dptr[0][i].birthdate[1] = i + 10; 
    dptr[0][i].birthdate[2] = i + 1990; 
}

for (int i = 0; i < 3; ++i) {
    printf("%d\\", dptr[0][i].birthdate[0]); 
    printf("%d\\", dptr[0][i].birthdate[1]); 
    printf("%d\n", dptr[0][i].birthdate[2]); 
}

/* Not to free the double pointer,
 * you have to free the inner pointer first then the outer pointers
 * Easy to remember is to free in reverse order of your allocation order
 */
for (int i = 0; i < 3; ++i) {
    free(dptr[0][i].birthdate);
    free(dptr[0]);
    /* free(dptr); this is not needed in this example because
     * dptr is pointer to address of a local variable,
     * but if it points to address of another array of detailOf* 
     * then this free is needed
     */ 
}

В вашем случае у вас есть только массив указателей, а не массив двойных указателей.

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

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

Вы выделяете maxSize указателей для person, но затем не можете выделить struct для каждого person[i] перед выделением для name и т. Д.

Таким образом, вы должны выделить структуру, например pointer[i] = malloc (sizeof *pointer[i]), прежде чем пытаться выделить person[i]->name = calloc(21, sizeof(char ));, ...

Также обратите внимание, что если вы выделяете на основе размера разыменованного указателя - вы никогда не будетеневерно определите ваше распределение (ваше распределение person является правильным только в результате счастливой случайности), например,

person = malloc (maxSize * sizeof *person);
...
person[i] = malloc (sizeof *person[i]);

(и обратите внимание, что [] или -> считается какразыменование)

person[i]->name = calloc (21, sizeof *person[i]->name);

Нет необходимости разыгрывать возврат malloc, это не нужно.См .: Я разыграю результат malloc?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...