In addition to the comments, your funciton has two primary problems, 1) you leak memory by overwriting the address of the first allocated block of memory; and 2) you attempt to return returnPath
which has automatic storage duration declared local to copyPath
.
Memory Leak
You leak memory in your function by overwriting the pointer temp
before it has been assigned, e.g.
struct path *temp = malloc(sizeof (struct path));
...
while (head != NULL) {
temp = malloc(sizeof (struct path));
By allocating a second time for temp
before you have assigned the original pointer to another variable, you lose the original pointer in temp
pointing to the first block of memory allocated. That memory can never be freed by your program from that point forward.
Returning Array with Automatic Storage Declared Local to Function
When I run it, I do not have anything in newPath and it is empty.
struct path *resultPath[2];
declares an array-of-pointers to struct path
(two of them). Automatic storage for resultPath
is declared local to copyPath
within it function stack frame. When copyPath
returns, all local variables with automatic storage duration are destroyed (function stack frame memory is released for reuse). This is expressly explained by C11 Standard - §6.2.4 Storage durations of objects
1) An object has a storage duration that determines its lifetime. There are four storage durations: static, thread, automatic, and allocated. Allocated storage is described in 7.22.3.
2) The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
6) For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.
(emphasis ours)
So, what is the best way to return these addresses and why I do not have it in newPath?
In order to return resultPath, you need to allocate storage for it dynamically and return a pointer to it. Objects with allocated storage duration extend for the lifetime of the program or until they are freed.
The easiest way to declare and allocate for an object capable of storing two pointers to struct path
is to declare an pointer-to-pointer to struct path, (effectively a dynamic array of pointers), and allocate storage for two pointers, e.g.
/* allocate & validate 2 pointers to struct path */
struct path **resultPath = malloc (sizeof *resultPath * 2);
if (!resultPath) { /* always validate all memory allocations */
perror ("malloc resultPath failed.");
return NULL;
}
...
resultPath[0] = newHead; /* newHead & newTail must point to allocated memory */
resultPath[1] = newTail;
return resultPath;
You can now safely return resultPath
and storage for resultPath
will survive the return eliminating your access of memory that is no longer available. You then access newHead
and newTail
through newPath[0]
and newPath[1]
, respectively, in the caller.
You will also need to change the return type for copyPath
to stuct path **
, e.g.
struct path **copyPath(struct path *head)
and update the type in the caller.