Why does this double mapping array almost work, but doesn't?
My code is as follows:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
double mapping [3][3];
} CoordinateMapperStr;
typedef CoordinateMapperStr * CoordinateMapper;
CoordinateMapper CoordinateMapper_Constructor(void)
{
CoordinateMapper this = (CoordinateMapper) calloc (1, sizeof(CoordinateMapper));
//return this; // <- I was missing this return, but still the rest worked the same
}
void CoordinateMapper_Initialize(CoordinateMapper this, double numb)
{
for (int i=0; i < 3; i=i 1) {
for (int j=0; j < 3; j=j 1) {
this->mapping[i][j] = numb;
printf("mapping(%d, %d) = %f\n", i, j, this->mapping[i][j]);
}
}
}
void CoordinateMapper_Print(CoordinateMapper this)
{
for (int i=0; i < 3; i=i 1) {
for (int j=0; j < 3; j=j 1) {
printf("mapping(%d, %d) = %f\n", i, j, this->mapping[i][j]);
}
}
}
int main()
{
CoordinateMapper mapper_1 = CoordinateMapper_Constructor();
CoordinateMapper_Initialize(mapper_1, 1);
printf("Init 1 done\n");
CoordinateMapper_Print(mapper_1);
printf("Print 1 done\n");
CoordinateMapper mapper_2 = CoordinateMapper_Constructor();
CoordinateMapper_Initialize(mapper_2, 2);
printf("Init 2 done\n");
CoordinateMapper_Print(mapper_1);
printf("Second print 1 done\n");
CoordinateMapper_Print(mapper_2);
printf("Print 2 done\n");
}
// Here is the corresponding output
user:~/path$ gcc src/test_3.c -o test_3
user:~/path$ ./test_3
mapping(0, 0) = 1.000000
mapping(0, 1) = 1.000000
mapping(0, 2) = 1.000000
mapping(1, 0) = 1.000000
mapping(1, 1) = 1.000000
mapping(1, 2) = 1.000000
mapping(2, 0) = 1.000000
mapping(2, 1) = 1.000000
mapping(2, 2) = 1.000000
Init 1 done
mapping(0, 0) = 1.000000
mapping(0, 1) = 1.000000
mapping(0, 2) = 1.000000
mapping(1, 0) = 1.000000
mapping(1, 1) = 0.000000 // This is not correct
mapping(1, 2) = 0.000000 // This is not correct
mapping(2, 0) = 0.000000 // This is not correct
mapping(2, 1) = 1.000000
mapping(2, 2) = 1.000000
Print 1 done
mapping(0, 0) = 2.000000
mapping(0, 1) = 2.000000
mapping(0, 2) = 2.000000
mapping(1, 0) = 2.000000
mapping(1, 1) = 2.000000
mapping(1, 2) = 2.000000
mapping(2, 0) = 2.000000
mapping(2, 1) = 2.000000
mapping(2, 2) = 2.000000
Init 2 done
mapping(0, 0) = 1.000000
mapping(0, 1) = 1.000000
mapping(0, 2) = 1.000000
mapping(1, 0) = 1.000000
mapping(1, 1) = 0.000000 // This is not correct
mapping(1, 2) = 0.000000 // This is not correct
mapping(2, 0) = 0.000000 // This is not correct
mapping(2, 1) = 1.000000
mapping(2, 2) = 1.000000
Second print 1 done
mapping(0, 0) = 2.000000
mapping(0, 1) = 2.000000
mapping(0, 2) = 2.000000
mapping(1, 0) = 2.000000
mapping(1, 1) = 2.000000
mapping(1, 2) = 2.000000
mapping(2, 0) = 2.000000
mapping(2, 1) = 2.000000
mapping(2, 2) = 2.000000
Print 2 done
- What is the proper way to setup a double array within a struct pointer?
- Why does each struct pointer seem to make it´s own new array, but still they are a bit flaky?
- What
gcc
compiler flags could I use to help me see this kind of error and the missingreturn this;
in the constructor?
CodePudding user response:
The problem is that whether you return this
or not, you get undefined behavior in either case.
When you don't return this
your non-void function doesn't return a value -- thus your code uses some garbage value (which might happen to be the return value from calloc
).
If you return this
-- you return allocation of sizeof(CoordinateMapper)
, which is just a size of a single pointer. This is less than your struct sizeof(CoordinateMapperStr)
, and your other code reads/writes beyond the allocated memory. This is, again, undefined behavior.