Hi All,
Any ideas what is wrong with the following very short program ?
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct my_struct myStruct;
struct my_struct {
int val;
};
myStruct *f2(void)
{
myStruct *dst = (myStruct*)calloc(5, sizeof(myStruct));
calloc() can fail. If it does, it returns a null pointer. If dst is
null, then the following statement has undefined behavior. Always check
for the possibility of failure whenever calling malloc(), calloc(), or
realloc(), and make sure NOT to dereference the pointers they return if
they are null.
dst->val = 5;
return dst;
}
void f1(myStruct *dst)
{
dst = f2();
printf("dst->val=%d\n", dst->val);
The variable dst in this program contains a copy of the pointer value
passed to it by the calling routine. It then replaces that pointer with
the one returned by f2(). As a result, there's no point in having the
caller pass that value. You might as well define dst inside of f1,
rather than making it a function argument. That's not the correct way to
fix this problem, but it's a key symptom of what's wrong with this function.
When f1 returns, the variable named "dst" declared in this function
ceases to exist, and the information stored in that value is lost.
Therefore, it's no longer possible to free() the memory allocated by
f2(). This is a memory leak. That's less important than the other
problem, but s
}
int main()
{
myStruct *src = (myStruct*)malloc(sizeof(myStruct));
myStruct *dst;
At this point, dst is uninitialized; that means that it's value is
indeterminate.
Since the value of dst is indeterminate, it might be a trap
representation, a value that does not represent any valid memory
location. Attempting to read a trap representation has undefined
behavior. There are real world machines where that could cause your
program to be aborted.
That statement causes a the value of dst in main() to be copied to the
variable named dst in f1(). There is otherwise no connection between
those two variables, they are two entirely different variables that
happen to have the same name.
Therefore, the fact that f1() changes the value of f1()'s variable named
"dst" has no affect whatsoever on the value of main()'s variable named
dst. That variable remains is uninitialized.
printf("dst->val in main=%d\n", dst->val);
Even if dst doesn't contain a trap representation, it points at some
unknown location on your machine. That location is almost certainly NOT
the same as the location allocated by the call to calloc() in f2(). It
might not be a piece of memory that your program has no right to access;
attempting to access it could get your program aborted. The behavior of
attempting to dereference that pointer in order to retrieve the value of
"val" is undefined.
It's also possible that whatever memory is stored at that location,
contains a trap representation for "int". That's less likely than the
pointer trap representation, but still possible. If so, that provides a
third reason why the behavior of your program is undefined.
}
Any ideas why, when running this program, I get:
dst->val=5
dst->val in main=1
Why is it 1 in main and not 5 ?
I would expect that in main it will also be 5.
What should I do so that in main it will be 5 ?
f1() needs to have some way of transmitting the pointer that it gets
from f2() back to main(). Here's the two best ways to do this:
1: return the pointer as the value of f1():
myStruct *f1(void)
{
myStruct *dst = f2();
printf("dst->val=%d\n", dst->val);
return dst;
}
in main():
dst = f1();
// after you're done with dst:
free(dst);
2. Pass a pointer to dst to f1(), and use that pointer to fill in dst:
void f1(myStruct **pdst)
{
if(pdst == NULL)
{
// Insert error handling here
return;
}
*pdst = f2();
}
in main():
f1(&dst);
// after you're done with dst:
free(dst);