This is an example in Vala code.
There is a global Glib.Llist vstack that stores some pointers.
List<void*> vstack;
There is a change_state function that stored the second parameter in the global vstack list.
void change_state( enum..., void*, enum... );
This goto_info test function (which calls change_state) doesn't work because, when it returns, the pointer is deallocated even if it is stored in the list
// Vala source
void goto_info()
{
StInfo sti = new StInfo();
change_state( SUPS.INFO_PAGE, sti, StackDir.FORW );
}
// C output
void goto_info (void) {
StInfo* sti = NULL;
StInfo* _tmp0_ = NULL;
_tmp0_ = st_info_new ();
sti = _tmp0_;
change_state (SUPS_INFO_PAGE, sti, STACK_DIR_FORW);
_g_object_unref0 (sti);
}
But if I just add the owned attribute, the code works (the pointer is not deallocated at the end of the goto_info function), but I really can't understand what changes in the C output.
// Vala source
void goto_info()
{
StInfo sti = new StInfo();
change_state( SUPS.INFO_PAGE, ( owned )sti, StackDir.FORW );
}
// C output
void goto_info (void) {
StInfo* sti = NULL;
StInfo* _tmp0_ = NULL;
StInfo* _tmp1_ = NULL;
_tmp0_ = st_info_new ();
sti = _tmp0_;
_tmp1_ = sti;
sti = NULL;
change_state (SUPS_INFO_PAGE, _tmp1_, STACK_DIR_FORW);
_g_object_unref0 (sti);
}
IMPORTANT: goto_info is the only function that changes if I add owned, nothing else is touched by the Vala compiler. Someone can explain where is the black magic hidden in this C output code? Why the second version works if the ref/unref call for the pointer are the same?
Note this line:
sti = NULL;
sti
is set to NULL
(while _tmp1_
is passed to change_state
instead), so the call to unref now is a noop:
_g_object_unref0 (sti);