0

Okay, so I faced quite an interesting problem while writing a little program in C. So I create a Data structure, which has a reference to and Integer variable. When I print out the type of the first field of the data structure, I get the correct result, so it prints out Integer. If I get to the function, it prints out Identity (which is the type of the structure wrapping the Integer), no matter how much I nest.

Identity myIdentity = NewIdentity(newInteger(5));
printf("%s\n",(*myIdentity.fields[0]).type); // => This prints Integer

//this is the function :
int matches(Data input, Data template) {
    printf("%s\n",(*input.fields[0]).type); // => This prints Identity 
    printf("%s\n", (*(*input.fields[0]).fields[0]).type); // => This prints Identity too

 //calling it has the result of printing out "Identity" two times
 matches( myIdentity, NewIdentity(newInteger(5));

update :

Okay so I don't know what's going on, but this is what happens when I call this :

Identity myIdentity = NewIdentity(newInteger(5));
printf("%s\n",(*myIdentity.fields[0]).type);
printf("%s\n",(*myIdentity.fields[0]).type);
printf("%s\n",(*myIdentity.fields[0]).type);
printf("%s\n",(*myIdentity.fields[0]).type);

out :

Integer
1�I��^H��H���PTL��
1�I��^H��H���PTL��
1�I��^H��H���PTL��

update :

typedef Data Identity;
typedef Data Integer;
typedef struct Data {
    struct Eval evaluator; //totally irrelevant for us
    char * type; 
    int enumeration;
    struct Data ** fields;
} Data;

Identity NewIdentity(Data x){
    Data retval;
    retval.evaluator = newEval(NULL,0,NULL,0,NULL); //irrelevant part
    retval.type = new_string("Identity"); //here's the type
    retval.enumeration = 0;
    retval.fields = ophoAlloc(2,sizeof(Data)); //basically just a straightup calloc at the moment
    retval.fields[0] = &x;
    retval.fields[1] = NULL;
    return retval;
}

Integer newInteger(int val) {
    Integer retval;
    retval.evaluator = newEval(NULL,0,NULL,0,NULL); //irrelevant
    retval.type = new_string("Integer");
    retval.enumeration = val; 
    retval.fields = NULL; 
    return retval;
}
Márton Kardos
  • 93
  • 2
  • 10
  • 3
    Please provide a [mcve] – klutt Mar 24 '18 at 22:42
  • 4
    Show the type definitions. The notation `(*(*input.fields[0]).fields[0]).type` is gruesome. Use `input.fields[0]->fields[0]->type` — the arrow operator `->` was invented for a reason, and you just demonstrated that reason. Also read about [Is it a good idea to typedef pointers?](https://stackoverflow.com/questions/750178/) — the short answer is "No, except perhaps for function pointers". – Jonathan Leffler Mar 24 '18 at 22:42
  • I didn't know it existed, but okay, I'll use it from now on, also, I'll post an update on type definitions – Márton Kardos Mar 24 '18 at 22:43
  • The fact that you get `Integer` on the first print and then get garbage for printing the same value again strongly indicates that you returned a pointer to a local variable that got overwritten by the first call to `printf()` but not until after the value had been used. Don't return pointers to local variables. – Jonathan Leffler Mar 24 '18 at 22:45
  • Not a single function in here is returning a pointer to anything, and the NewIdentity function gets the value from the outer scope, and than puts a reference to that in the fields field. – Márton Kardos Mar 24 '18 at 22:57
  • There are no pointer typedefs anywhere – Márton Kardos Mar 24 '18 at 23:01
  • Agreed, no pointer typedefs present in what's shown; that's good. No functions returning pointers; also good. However, it still isn't an MCVE ([MCVE]) because you call `ophAlloc()` and other functions for which the implementation is not present. That makes it hard for people to help you. I see you've self-answered the question. You are using a pointer to a structure passed on the stack in the structure, which vanishes when the function returns (just like any other local variable vanishes), and you return a copy of that structure containing the pointer. It's an interesting variant, but… – Jonathan Leffler Mar 25 '18 at 00:08
  • ophoAlloc is a calloc, but I wrote it in a comment. newEval is an overly complicated thing, which isn't required in order to understand the problem at all. new_string() allocates a string on the heap with ophoAlloc(), that's all that it does – Márton Kardos Mar 25 '18 at 09:16

1 Answers1

0

Okay, so my problem was, that in the data constructor, instead of reallocating the whole thing, I was just lazy and went like this :

retval.fields[0] = &x;

turns out it wasn't quite right, this way it works perfectly :

retval.fields[0] = ophoAlloc(1,sizeof(Data));
    retval.fields[0][0] = x;
Márton Kardos
  • 93
  • 2
  • 10