Reputation: 17
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
struct date {
int year;
int month;
int day;
};
struct person{
char name[64];
struct date birthday;
};
struct aop {
int max;
struct person **data;
};
struct aop *create_aop(int max) {
struct aop *new = malloc(sizeof(struct aop));
new->data = malloc(max*sizeof(struct person));
for (int i=0; i<max; i++) {
new->data[i] = NULL;
}
new->max = max;
return new;}
void destroy_aop(struct aop *a) {
free(a->data);
free(a);
}
int add_person(struct aop *a, char *name, struct date birthday) {
if (a->data[a->max-1] != NULL) {
return -1;
}
struct person *new_person = malloc(sizeof(struct person));
strcpy(new_person->name, name);
new_person->birthday = birthday;
for (int i=0; i<a->max; i++) {
if (a->data[i] == NULL) {
a->data[i] = new_person;
break;
}
}
free(new_person);
return 0;
}
I have some questions about the code I wrote. First, do I need to add extra codes into create_aop to initialize name and birthday inside of person? And I found that after the free(new_person) in add_person, I cannot reach a->data[0]->name. How can I change the of a->data[i] without using another pointer?
struct aop *birthdays(const struct aop *a, int month) {
int m = a->max;
struct aop *n = create_aop(m);
int j = 0;
for (int i=0; i<m; i++) {
if (a->data[i] != NULL) {
if (a->data[i]->birthday.month == month) {
n->data[j] = a->data[i];
j++;
}
} else {
break;
}
}
if (j == 0) {
return NULL;
}
return n;
}
Every time I run the function above, there are some errors memory. I have been thinking about it for hours but have no idea what is wrong in this one.
Upvotes: 0
Views: 123
Reputation: 1682
There are two big mistakes in this code. First, the allocation of your data array in struct aop is flawed.
new->data = malloc(max*sizeof(struct person));
You don't want it to point to memory of size max times length of a person struct, do you? Since it is a pointer to pointers, it's size only has to be max times length of a pointer, i.e.
new->data = malloc(max*sizeof(struct person*));
You could also let data directly point to struct person. Then the first line would be correct and you don't have to allocate memory each time you create a new person. Instead, you would just use the memory that data points to:
(aop->data[i]).name = ...
and so on.
Secondly, you are freeing your person struct right after creation.
free(new_person);
Now aop->data[i] is a dangling pointer, because the address it points to could be overwritten any time (because it's not locked by malloc anymore). Instead, you have to free it in your destroy function. It might look something like this:
void destroy_aop(struct aop *a) {
int i;
for(i = 0; i < a->max; i++)
{
if(a->data[i] != NULL) {
free(a->data[i]);
}
}
free(a->data);
free(a);
}
Upvotes: 1