2

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;
}
19
  • Post a minimal self contained example please. Commented Oct 18, 2016 at 7:20
  • Are you saying that you have allocated for 10 Account structs, and are accessing with all_accounts[10], which would of course be out of bounds? Commented Oct 18, 2016 at 7:27
  • No, I'm saying if I try to access a member variable, it segfaults, not 10 specifically. Commented Oct 18, 2016 at 7:30
  • Your example does not compile. Commented Oct 18, 2016 at 7:32
  • 1
    all_accounts[i]->accountNo = i; --> (*all_accounts)[i].accountNo = i; Commented Oct 18, 2016 at 7:44

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. That was my main problem. I thought the all_accounts[i] returned a pointer to a struct rather than a struct. The dot notation makes more sense now.
2

As you wrote, to allocate space for all_accounts_dyn you used

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

It is correct due to the double pointer.

The double pointer takes the address of pointer all_accounts_dyn

The returned address of malloc is assigned to all_accounts_dyn that is *all_accounts inside the dynamicStruct function.

So when you loop to init the struct you have to first dereference the double pointer and the dereference all_accounts_dyn items.

    for(int i = 0; i<num_accounts;i++)
    {
        (*all_accounts)[i].accountNo = i;

        printf("initialized %d\n", (*all_accounts)[i].accountNo);

    }

Comments

-1

If you are trying to allocate an araay of structs,then why are you using double pointers.

all_acounts=(Acount*)malloc(sizeof(Acount)*num_acounts) and in the function dynamicStruct set the argument as normal non double pointer *all_acounts

3 Comments

stackoverflow.com/questions/5580761/… Second answer: Use ** when you want to preserve (OR retain change in) the Memory-Allocation or Assignment even outside of a function call.
This doesn't answer the question. If you don't understand something in the question, please refrain from posting an answer. Instead, ask a new question.
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
-1

the posted code contains several problems.

  1. incorrect return value from main()
  2. unused return value from dynamicStruct()
  3. using wrong type when passing num_accounts
  4. needs appropriate vertical and horizontal spacing, for readability
  5. does not properly set the values in the array of structs
  6. fails to check for errors in call to malloc()
  7. contains several risky conversions between different numeric types
  8. contains tabs for indenting the code
  9. does not indent the code consistently
  10. returns a misleading value from the main() function
  11. casts the returned value from malloc(), which is a bad practice in C

and now the corrected code:

#include <stdio.h>   // printf()
#include <stdint.h>  // int8_t 
#include <stdlib.h>  // malloc(), exit(), EXIT_FAILURE
//#include <stdbool.h>

struct Account
{
    int8_t accountNo;
};

void dynamicStruct( struct Account **all_accounts, size_t num_accounts );

int main( void )
{
    struct Account *all_accounts_dyn;
    size_t num_accounts = 10;
    dynamicStruct( &all_accounts_dyn, num_accounts );
} // end function: main


void dynamicStruct( struct Account **all_accounts, size_t num_accounts )
{
        *all_accounts = malloc(sizeof(struct Account)*num_accounts);
        if( NULL == *all_accounts )
        {
            perror( "malloc for account array failed" );
            exit( EXIT_FAILURE );
        }

        // implied else, malloc successful


        for( int8_t i = 0; i<(int8_t)num_accounts; i++ )
        {
            printf("initializing %d\n",i);
            (*all_accounts)[i].accountNo = i;
        }
} // end function: dynamicStruct

The above code outputs the following:

initializing 0
initializing 1
initializing 2
initializing 3
initializing 4
initializing 5
initializing 6
initializing 7
initializing 8
initializing 9

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.