The Crystal Programming Language Forum

C Struct Pointer Binding Passes Wrong Values

If I have the following C code:

typedef struct {
    int    i;
  } Info;

typedef struct {
            int type;
             Info* info;
             } Data;

Data* myFunc() {
  Data *d = (Data*)malloc(sizeof(Data));

  Info in;
  in.i = 5 ;
  Info *s = ∈
  d -> type = 1;
  d -> info = s;
  //printf("Value: %d\n", ((Info*)(d -> info))->i );
  return d;
}

And matching Crystal code:

@[Link(ldflags: "#{__DIR__}/functions.o")]
lib LibCTest

  struct Data
    type : Int32
    info : Info*
  end

  struct Info
    i : Int32
  end

  fun myFunc() : Data*

end

p       LibCTest.myFunc().value.info.value.i

I build the library with: gcc -Wall -O3 -march=native -c functions.c -o functions.o

The correct value of info.i is never passed i.e., 5. It will be passed if I uncomment the printf and re-compile strangely. This also happens if the struct Info pointer is void* instead.

Any thoughts on what I’m doing wrong, I can’t find any posts or documentation on embedded C struct pointers.

The C implementation of myFunc has a bug: info is a pointer and you assign a stack pointer to it and return it from the function. But that pointer becomes invalid when leaving the scope of myFunc. It might still work in some cases, like the printf expression shows, but that’s just lucky.
You’ll be able to observe the same behaviour calling myFunc from C.

To fix this, you could allocate *s on the heap, just like *d.

1 Like