I wrote a program to test retrieving a pointer (to a struct) from a function via double-pointer 'out' parameter:
#include <stdio.h>
#include <stdint.h>
struct mastructrure_t
{
int a;
int b;
};
int Test(struct mastructrure_t **var5)
{
struct mastructrure_t *var3;
struct mastructrure_t test;
test.a = -1313;
test.b = -1414;
var3 = &test;
printf("addr pointer var1= %p\n", var5);
printf("\n");
printf("addr test= %p\n", &test);
printf("addr3 similaire test=%p\n", var3);
*var5 = var3;
printf("var addr test= %p\n", *var5);
printf("addr a=%p\n", &(var3->a));
printf("addr b=%p\n", &(var3->b));
return 0;
};
int main(int argc, char **argv)
{
struct mastructrure_t *var1;
printf("addr pointer var1= %p\n", &var1);
Test(&var1);
printf("addr a=%p\n", &(var1->a));
printf("addr b=%p\n", &(var1->b));
//printf("%s", "\n");
printf("a=%d\n", var1->a);
printf("b=%d\n", var1->b);
return 0;
}
That code works. The printf
calls show var1->a = -1313 and var1->b = -1414. But if I uncomment the commented-out printf
call, the output shows different values for var1->a
and var1->b
! I don't understand why. Does my code have a memory leak? Am I'm not using printf
in the right way?
I was hoping in each case to see:
var1->a = -1313
var1->b = -1414
That code works. The printf calls show var1->a = -1313 and var1->b = -1414.
That's plausible, but in no way guaranteed.
But if I uncomment the commented-out
printf
call, the output shows different values forvar1->a
andvar1->b
!
That's also plausible.
Does my code have a memory leak? Am I'm not using
printf
in the right way?
No and no. The issue is that using parameter var5
, your Test()
function is setting main()
's var1
to point to a local variable of Test()
. There's no problem with that while Test()
is executing, but that local (structure) variable's lifetime ends as soon as execution of Test()
completes. After Test()
returns, it is no longer defined what var1
points, so dereferencing that pointer produces undefined behavior.
UB does not necessarily mean that your program will crash, or even that it will behave differently than you (without justification) expect. But it might do. And it might behave differently on different runs, or produce unexpected behavior only for some inputs. One of the classic telltales of UB is that small program changes produce unrelated changes in behavior.
You have several alternatives for fixing your program, among them:
Test()
could allocate memory dynamically for the wanted structure. That would then put an onus on main()
to free that memory when no longer needed.
Test()
could provide a pointer to a file-scope variable or a static
local variable (these have lifetime that extends throughout the entire run of the program).
main()
could provide the object, passing a single pointer to it to Test()
, with the latter function filling it in.