0

I need to have a global dynamic array of pointers, in which I will store my structs, beacuse later I will need to iterate through this array to list all the stored information, I also need to be able to read the name, age and job variables from the console, and store them in a person_t in the iterator array.

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

typedef struct Person
{
    char name[30];
    int age;
    char job[30];
} person_t;

person_t **iterator;
int capacity = 10;
int size = 0;

int main()
{
    int i;
    *iterator = (person_t *)malloc(capacity * sizeof(person_t));
    for (i = 0; i < capacity; ++i)
    {
        person_t p;
        p.age = i;
        *iterator[i] = p;
    }
    return 0;
}

I get no errors/warnings compiling this code (gcc -ansi -pedantic -Wall -Wextra), but when I try to run it, I get a Segmentation fault immediately.

1
  • no need to cast malloc Commented Dec 2, 2020 at 18:31

3 Answers 3

3

When you do this:

*iterator = (person_t *)malloc(capacity * sizeof(person_t));

You're deferencing iterator, however as a file-scope pointer variable it's initialized to NULL. Attempting to dereference a NULL pointer invokes undefined behavior.

I suspect what you really want is an array of structs, not an array of pointers to structs. That being the case, define iterator as:

person_t *iterator;

Then you allocate memory for it like this:

iterator = malloc(capacity * sizeof(person_t));

Then assign to array elements like this:

iterator[i] = p;
Sign up to request clarification or add additional context in comments.

Comments

1

Your stated purpose is to create a "global dynamic array of pointers, in which I will store my structs". The following modification of your code (see comments) will do this:

person_t p[10] = {0};

int main()
{
    int i;
    // with declaration: person_t **iterator = NULL;, 
    //following is all that is needed to create an array of pointers:
    iterator = malloc(capacity * sizeof(person_t *));//no need to cast return of malloc
   
        
        for (i = 0; i < capacity; ++i)
        {
            //person_t p;//moved to scope that will exist outside of main()
            p[i].age = i;
            iterator[i] = &p[i];//assign the address of the object to the pointer
                             //iterator[i] is the ith pointer in a collection of 
                             //pointers to be assigned to point to 
                             //instances of struct person_t 
        }
        //Once all fields are populated (to-do), the following will display the results:
        for (i = 0; i < capacity; ++i)
        { 
           printf("%d) Name: %s Age: %d  Job: %s\n",  i, iterator[i]->name,iterator[i]->age,iterator[i]->job);
        }

    return 0;
}

3 Comments

Worth pointing out that "iterator" is really a misnomer as that is the primary storage for that collection of person_t. people would make more sense and then declare a person_t *iterator to use as a temporary pointer to actually iterate over the collection of people.
@DavidC.Rankin - I do not disagree. My attempt here however was to use a strict literal interpretation of what OP asked for, and in doing that, stick with OP variable descriptions, thus allowing OP to easily track items in request with steps in my implementation. Using OP naming conventions helps to that end.
I understand, and I agree it helps to track the naming used in the question. That's why I didn't suggest a change, but just that it was worth pointing out so at least they are cognizant of descriptive naming being helpful. The comment will do.
0

you are not allocating memory correctly

First you need to allocate memory for a pointer which can store capacity number of address i.e done through iterator = malloc(capacity * sizeof(person_t*)); and then you need to allocate memory for holding each structure element i.e iterator[i] = malloc(sizeof(person_t));

all the malloc'ed memory should be free'd once we are done with it.

Also, have not done the error check for malloc's , that is left as an exercise for you.

int main()
{
    int i;
    // test data
    char *names[] = {"ABC", "DEF"};
    char *jobs[] = {"Accountant", "Security"};
    int ages[] = {50, 60};
    
    // first allocate memory for iterator , which can hold pointers to store iterator poniters
    iterator = malloc(capacity * sizeof(person_t*)); 
    
    for (i = 0; i < capacity; ++i)
    {
        // now allocate memory for individual iterator
        iterator[i] = malloc(sizeof(person_t)); 
        strcpy(iterator[i]->name,names[i]);
        iterator[i]->age = ages[i];
        strcpy(iterator[i]->job, jobs[i]);
    }
    
    for (i = 0; i < capacity; ++i)
    {
        printf("name = %s ", iterator[i]->name);
        printf("Age = %d ", iterator[i]->age);
        printf("Job = %s\n", iterator[i]->job);
    }
    return 0;
}

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.