Nawar Ismail
Nawar Ismail

Reputation: 75

Malloc 'ing array of struct in struct

I've been doing research for a while, and I'm not finding anything that helps me.

I have the following struct declarations:

typedef struct position_struct{
    int x;
    int y;
} pos;

typedef struct item_struct{
    char member1;
    pos member2;
} item;

typedef struct room_stuct{
    item * member3;
    pos * member4;
    pos member5;
} roomLayout;

And the code to try to malloc it is (I removed the error checking for brevity):

 roomLayout *genFloor () {
                                                         // Allocate mem for Arrays of:
    roomLayout * room = malloc(sizeof(roomLayout) * 6 ); //     6 rooms
    room->member3     = malloc(sizeof(item)       * 10); //     10 member3's
    room->member4     = malloc(sizeof(pos)        * 10); //     10 member4's

    /* TESTING */
    room[0].member3[0].member1 = 'd';
    printf("Room[0] is good\n");
    room[1].member3[0].member1 = 'd';
    printf("Room[1] is good\n");           // Never prints/makes it to this line


    return room;
 }

When I try this, assigning to room[1] causes a crash, but not room[0]. My guess is that I havent actually allocated enough space for the whole array and only one spot. But I don't understand why as I believe that I'm following what I see everywhere else.

If someone could please explain to me the procedure for allocating memory for this kind of setup, that would be very helpful! Thank you.

Upvotes: 3

Views: 153

Answers (4)

R_Kapp
R_Kapp

Reputation: 2858

You are only allocating member3 and member4 for the first room; not for all of them. In the line room->member3, room is at the beginning of the memory segment, or at room[0], which allocates space for 10 member3s. room[1], however, has not allocated any space for any member3s (similarly for doors). Work around this by allocating in a loop:

for(i = 0; i < 6; ++i)
{
    room[i].member3 = malloc(sizeof(room[i].member3) * 10);
    room[i].member4 = malloc(sizeof(room[i].member4) * 10);
}

When free-ing the memory, remember to use a similar loop, i.e.

for(i = 0; i < 6; ++i)
{
    free(room[i].member3);
    free(room[i].member4);
}

free(room);

Upvotes: 5

Aviv
Aviv

Reputation: 424

You are missing allocation to room[1], room[2] and so on. by room->groundItems = malloc... you implcitly say room[0].groundItems = malloc ....

Maybe the allocation of six places of roomLayout confused you. It allocated the pointers to groundItems and doors arrays, but not the space they required themselves.

Upvotes: 0

Rabbid76
Rabbid76

Reputation: 211277

You allocated groundItems and doors only for the first room, But you have to allocate it for all 6 rooms. Each room needs its own list of groundItems and doors. Adapt your code like this:

roomLayout * room = malloc(sizeof(roomLayout) * 6 ); //     6 rooms
for ( int i = 0; i < 6; i ++ )
{
    room[i].groundItems = malloc(sizeof(item)       * 10); //     10 ground items
    room[i].doors       = malloc(sizeof(pos)        * 10); //     10 doors
}

Note room->groundItems is similar to room[0].groundItems. So in your case room[0].groundItems[0].objectID worked, but room[1].groundItems[0].objectID failed, because room[1].groundItems was never initialized.

Upvotes: 1

LPs
LPs

Reputation: 16243

room->groundItems = malloc(sizeof(item) * 10);

The code above allocate a 10 items for only for room[0].

room[1 to 5] are not allocated and access them is UB.

You must allocate all your pointers before to access them, like showed below

roomLayout * room = malloc(sizeof(roomLayout) * 6 )
for (int i=0; i<6; i++)
{
    room[i].groundItems = malloc(sizeof(item) * 10); //     10 ground items
    room[i].doors       = malloc(sizeof(pos)  * 10); //     10 doors
}

Upvotes: 2

Related Questions