Reputation: 49
I'm working on a code which handles traffic in intersections over time and returns how much traffic there is in an intersection at a given time.
Basically the problem I have is with an array of structs where each struct contains 2 vectors: one with intersection's coordinates (x, y) and the other one keeps track of how many cars passed at time t into that intersection (every slot from 0 to n represents time, the value inside is the number of cars that crossed at that time).
Here's the struct:
typedef struct intersection {
int coords[2];
int timeslots[];
} intersection;
which is contained in intersections array from this struct:
typedef struct simulation {
int h_streets; //row (horizontal streets)
int v_streets; //column (vertical streets)
int n_cars; //cars number
int n_trips; //trips number
car car_pos [1000];
intersection intersections [];
} simulation;
Memory is then allocated with malloc to define actual array size for flexible arrays when needed data are read:
struct simulation * this = malloc( sizeof(simulation) + (sizeof(intersection)*(h_streets*v_streets)*(sizeof(int)*(max_time+1001))) );
When reading data regarding a car's trip from one position to another, what I do is, as said before, incrementing timeslots[t] by one when the car crosses that intersection at that time.
The issue is that, when I do so with this line of code contained in a while cycle
this->intersections[curr_int].timeslots[starting_t+travel_t]++;
the value from coords array are modified.
Here's an example when printing out just the intersections coordinates at each cycle:
------------------
i: 0, h: 0, v: 0
i: 1, h: 0, v: 1
i: 2, h: 0, v: 2
i: 3, h: 0, v: 3
i: 4, h: 1, v: 0
i: 5, h: 1, v: 1
i: 6, h: 1, v: 2
i: 7, h: 1, v: 3
i: 8, h: 2, v: 0
i: 9, h: 2, v: 1
i: 10, h: 2, v: 2
i: 11, h: 2, v: 3
i: 12, h: 3, v: 0
i: 13, h: 3, v: 1
i: 14, h: 3, v: 2
i: 15, h: 3, v: 3
------------------
------------------
i: 0, h: 0, v: 0
i: 1, h: 1, v: 1
i: 2, h: 0, v: 2
i: 3, h: 0, v: 3
i: 4, h: 1, v: 0
i: 5, h: 1, v: 1
i: 6, h: 1, v: 2
i: 7, h: 1, v: 3
i: 8, h: 2, v: 0
i: 9, h: 2, v: 1
i: 10, h: 2, v: 2
i: 11, h: 2, v: 3
i: 12, h: 3, v: 0
i: 13, h: 3, v: 1
i: 14, h: 3, v: 2
i: 15, h: 3, v: 3
------------------
------------------
i: 0, h: 0, v: 0
i: 1, h: 1, v: 2
i: 2, h: 0, v: 2
i: 3, h: 0, v: 3
i: 4, h: 1, v: 0
i: 5, h: 1, v: 1
i: 6, h: 1, v: 2
i: 7, h: 1, v: 3
i: 8, h: 2, v: 0
i: 9, h: 2, v: 1
i: 10, h: 2, v: 2
i: 11, h: 2, v: 3
i: 12, h: 3, v: 0
i: 13, h: 3, v: 1
i: 14, h: 3, v: 2
i: 15, h: 3, v: 3
------------------
------------------
i: 0, h: 0, v: 0
i: 1, h: 1, v: 2
i: 2, h: 0, v: 2
i: 3, h: 0, v: 3
i: 4, h: 2, v: 0
i: 5, h: 1, v: 1
i: 6, h: 1, v: 2
i: 7, h: 1, v: 3
i: 8, h: 2, v: 0
i: 9, h: 2, v: 1
i: 10, h: 2, v: 2
i: 11, h: 2, v: 3
i: 12, h: 3, v: 0
i: 13, h: 3, v: 1
i: 14, h: 3, v: 2
i: 15, h: 3, v: 3
------------------
[...]
(i is the counter for the cycle which accesses intersections[] in position i, whereas h and v are horizontal and vertical coordinates of the intersection i contained in the coords[] array)
As you can notice, coordinates of some intersections are modified after every cycle even though I'm not even accessing that array with the incrementing function
this->intersections[curr_int].timeslots[starting_t+travel_t]++;
which is the one causing this problem. How is this possible? Could it be a memory allocation issue?
Upvotes: 0
Views: 68
Reputation: 222846
In this code that declares a member of simulation
:
intersection intersections [];
intersections
is a structure with a flexible array member, so the code above attempts to create an array of structures with a flexible array member.
This cannot work. The size of a structure with a flexible array member is as if the flexible array member were omitted (except for a potential issue about padding for alignment). This compiler cannot account for the sizes of flexible arrays when calculating the structure size or performing array index calculations.
This code attempts to use the array of structures with flexible array members:
this->intersections[curr_int].timeslots[starting_t+travel_t]++;
In this code, the compiler cannot know how many elements the array this->intersections[curr_int].timeslots
has. Since timeslots
is a flexible array member, each instance of an intersection
may have a different number of elements in its timeslots
—the intent is for the programmer to provide whatever amount of space is desired for each instance. Because this amount may vary with each instance, they cannot be arranged into an array of fixed-size elements, and the compiler cannot know how big each one is.
Since the compiler does not know how many elements the programmer intends there to be in each timeslots
, it does not know how big each intersection
is. When calculating the address for this->intersections[curr_int]
, the compiler only uses the size of the structure as if defined without the flexible array member (except for the padding issue). This calculation will not be correct when the programmer intends flexible array members to be present.
Both Clang and GCC warn about this when the -pedantic
switch is used.
An array of structures with flexible array members cannot work. You must use another design for your structures. In each intersection
, timeslots
could be a pointer to space for the array of time slots instead of being a flexible array member.
Upvotes: 2