Struct with array of structs of unknown size

后端 未结 5 523
臣服心动
臣服心动 2021-02-05 12:35

I\'ve been trying to wrap my head around this the whole day...

Basically, I have a struct called State that has a name and another one called StateMachine with a name, a

相关标签:
5条回答
  • 2021-02-05 13:03
    State ** states;
    

    will create an array of state arrays.

    I haven't read through the whole solution truthfully (gotta run), but you mentioned wanting an array of states - did you possibly want to do:

    State* states
    

    or

    State states[size];
    

    instead? Just food for thought, chances are it wasn't your problem since I didn't fully read it :p

    0 讨论(0)
  • 2021-02-05 13:04

    It looks like you want to have a variable number of states in each state machine, but you are allocating the memory incorrectly. In create_state_machine, this line:

    temp->states = malloc(sizeof(struct State));
    

    Allocates a single State object, not an array of pointers (which is how you are using it).

    There are two ways you could change this.

    1. Declare states as State states[<some-fixed-size>]; but then you cant ever have more than a fixed number of states.
    2. Add another member to indicate how much storage has been allocated for states, so you can keep track of that as well as how much is used (which is what total_states is being used for).

    The later would look something like this:

    #include <stdlib.h>
    #include <string.h>
    
    typedef struct 
    {
        const char *name;
    } State;
    
    typedef struct 
    {
        const char *name;
        int total_states;
        int states_capacity;
        State *states;
    } StateMachine;
    
    StateMachine *create_state_machine(const char *name)
    {
        StateMachine *temp = malloc(sizeof(StateMachine));
        memset(temp, 0, sizeof(*temp));
    
        temp->name = name;
        temp->states_capacity = 10;
        temp->states = malloc(sizeof(State) * temp->states_capacity);
    
        return temp;
    }
    
    State *add_state(StateMachine *machine, const char *name)
    {
        if (machine->total_states == machine->states_capacity)
        {
            // could grow in any fashion.  here i double the size, could leave
            // half the memory wasted though.
            machine->states_capacity *= 2;
    
            machine->states = realloc(
                machine->states, 
                sizeof(State) * machine->states_capacity);
        }
    
        State *state = (machine->states + machine->total_states);
        state->name = name;
    
        machine->total_states++;
    
        return state;
    }
    
    0 讨论(0)
  • 2021-02-05 13:22

    You're doing a conceptual error:

    State ** states;
    

    It's true that you can consider states like an array of pointer to State object, but you are allocating space for just one state. When you do:

    state_machine->states[state_machine->total_states]= temp;
    

    you are doing something wrong if total_states is greater than zero because you are pointing to memory segments that are not been allocated (I'm wondering why you don't get a SEGFAULT). To store a dynamic number of State this way you need a linked list, or to call realloc every state you add(but that's not a good idea). The memory you are allocating with different malloc calls isn't continuous.

    0 讨论(0)
  • 2021-02-05 13:28

    It looks like you're not allocating space for your states in the machine past the first one.

    StateMachine * create_state_machine(const char* name) {
      StateMachine * temp;
    
      temp = malloc(sizeof(struct StateMachine));
    
      if (temp == NULL) {
        exit(127);
      }
    
      temp->name = name;
      temp->total_states = 0;
    
      temp->states = malloc(sizeof(struct State)); // This bit here only allocates space for 1.
      return temp;
    }
    

    You're probably better off putting an array of states of fixed size in the state machine struct. If that's not okay, you'll have to realloc and move the whole set around or allocate chunks and keep track of the current length, or make a linked list.

    Incidentally, init, foo, and bar never get used.

    Edit: What I'm suggesting looks like this:

    #define MAX_STATES 128 // Pick something sensible.
    typedef struct StateMachine {
      const char * name;
      int total_states;
      State *states[MAX_STATES];
    } StateMachine;
    
    0 讨论(0)
  • 2021-02-05 13:28

    Inside of your add_state function:

    temp = malloc(sizeof(struct StateMachine)); 
    

    should be

    temp = malloc(sizeof(struct State));
    

    However, even when this is changed, I still get the proper output:

    --> [0] state: Init
    --> [1] state: Foo
    --> [2] state: Bar
    

    Perhaps there's nothing wrong with your code. I'm using gcc version 4.4.3

    0 讨论(0)
提交回复
热议问题