Search code examples
cmemory-managementdynamic-allocation

Dynamically allocated array of structs passed to function and accessed with indexing


I'm trying to dynamically allocate an array of structs by passing the pointer to a function. I need to access the array using indexing. I've got a similar proccess working without passing to a function. I have a simple struct called Account that only has one member, accountNo. Listed below is the relevant malloc call

int8_t dynamicStruct(struct Account **all_accounts,int8_t num_accounts){
    *all_accounts = (struct Account*)malloc(sizeof(struct Account)*num_accounts);
}

The variable all_accounts is initialized and called with the following snippet, with num_accounts at this point being 10;

struct Account *all_accounts_dyn;
dynamicStruct(&all_accounts_dyn,num_accounts);

Accessing the member variable accountNo with the following method

all_accounts[i]->accountNo = i;

The program compiles fine, manages to allocate the memory, but segfaults upon accessing a member (num_accounts = 10).

Compiled with

gcc -std=gnu99 -Wall -Werror structify.c -o structify

"Small self contained example"

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

struct Account{
    int8_t accountNo;
};
int8_t dynamicStruct(struct Account **all_accounts,int8_t num_accounts);

int main(){
    struct Account *all_accounts_dyn;
    int8_t num_accounts = 10;
    dynamicStruct(&all_accounts_dyn,num_accounts);
    return 1;
}
int8_t dynamicStruct(struct Account **all_accounts,int8_t num_accounts){
        *all_accounts = (struct Account*)malloc(sizeof(struct Account)*num_accounts);
        for(int i = 0; i<num_accounts;i++){
            printf("initializing %d\n",i);
            all_accounts[i]->accountNo = i;
        }
        return 1;
}

Solution

  • When you have struct my_struct;, you access the members like this:

    mystuff = my_struct.stuff;
    

    But when you have a pointer to a struct struct *my_struct;, you do:

    mystuff = my_struct->stuff;
    

    This is equivalent to:

    mystuff = (*my_struct).stuff;
    

    In other words, you have to dereference the pointer to struct before you can access its member fields.

    When you allocate memory for 10 structs:

    *all_accounts = (struct Account*)malloc(sizeof(struct Account)*num_accounts);
    

    and then access with array notation, you have all_accounts[i] ==> *(all_accounts + i). So, all_accounts[i] is a struct, not a pointer to a struct, and must be accessed with the dot operator.