1

I have a function that is called recursively a number of times. Inside this function I malloc memory for a struct and pass it as an argument into the recursive call of this function. I am confused whether I can keep the name of the variable I am mallocing the same. Or is this going to be a problem?

struct Student{
     char *studentName;
     int studentAge;
  };

recursiveFunction(*struct){ //(Whoever calls this function sends in a malloced struct)
    Student *structptr = malloc(sizeof(Student));
    <Do some processing>
             .
             .
   if(condition met){
       return;
   }
   else{
       recursiveFunction(structptr);
   }
}

free(){} // All malloced variables are free'd in another function

Would this be a problem since the name of the variable being malloced doesnt change in each recursive call.

Brandon
  • 401
  • 5
  • 20
  • 2
    Please show [a complete example that actually compiles](https://stackoverflow.com/help/mcve). You can [edit your post](https://stackoverflow.com/posts/35069738/edit) to add the missing bits. – 5gon12eder Jan 28 '16 at 19:04
  • Since the function returns nothing, how can the malloc'd variables be freed elsewhere? – Schwern Jan 28 '16 at 19:07
  • How can you free all malloced memory in another function? Are you storing the pointers in another data structure? – Jay Jan 28 '16 at 19:07

4 Answers4

1

Each malloc() must have a matching free(). Either you need to free the record inside recursiveFunction (e.g. immediately before it exits), or in a function called by recursiveFunction or you need to maintain a list of them and free them elsewhere.

The name of the 'variable being malloced' being the same is irrelevant. In any case, it is not the variable that is being malloc()d; rather it is memory that is being malloc()d and the address stored in a variable. Each recursive iteration of recursiveFunction has a different stack frame and thus a different instance of this variable. So all you need to do is ensure that each malloc() is paired with a free() that is passed the address returned by malloc().

If you want to check you've done your malloc() / free() right, run valgrind on the code.

abligh
  • 24,573
  • 4
  • 47
  • 84
  • I forgot to mention, that I am storing the pointers of each of the new mallocs in a structure. By doing this I will be able to free them in another function by passing the data structure with all the pointers right? – Brandon Jan 28 '16 at 19:28
  • Sure, provided the function you call at the end walks through that data structure and frees the allocated memory based on those pointers. – abligh Jan 28 '16 at 21:56
1

The short answer is no. When you declare a variable it is scoped at the level where it is declared, in your case within this function. Each successive recursive call creates a new scope and allocates that memory within that scope so the name of your variable will not cause problems. However, you do want to be very careful that you free any memory that you malloc() before returning from your function as it will not be accessible outside the scope of your function unless you pass back a pointer to it. This question provides a lot of helpful information on using malloc() within functions. I also recommend reading more about scope here.

Community
  • 1
  • 1
Rainbacon
  • 933
  • 1
  • 16
  • 24
0

Can keep the name of the variable I am mallocing the same?

Yes, in a recursive function this is fine. As the function is called recursively, each variable holding the malloc'd pointer (it doesn't hold the memory itself) will be allocated on a new stack frame.

However, you're going to have to free that memory somehow. Only the pointer to the memory is on the stack, so only the pointer is freed when the function exits. The malloc'd memory lives on. Either at the end of each call to the function, or all that memory will have to be returned as part of a larger structure and freed later.

Schwern
  • 153,029
  • 25
  • 195
  • 336
0

I am confused whether I can keep the name of the variable I am mallocing the same.

You seem to be confused about the concept of scope. Functions in C define scopes for the (local) variables you declare within them. That means that when you declare a local variable bar inside some function foo, then when you reference bar inside that function you reference whatever you declared it to be.

int bar = 21;
void foo(void) {
  int bar = 42;
  // ...
  bar; // This is the bar set to 42
}

Now scope is only the theoretical concept. It's implemented using (among other details that I skip over here) so called stack frames:

When you call foo, then a new stack frame is created on the call stack, containing (this is highly dependent on the target architecture) things like return address (i.e. the address of the instruction that will be executed after foo), parameters (i.e. the values that you pass to a function) and, most importantly, space for the local variables (bar).

Accessing the variable bar in foo is done using addresses relative to the current stack frame. So accessing bar could mean access byte 12 relative to the current stack frame.

When in a recursive function the function calls itself, this is handled (mostly, apart from possible optimizations) like any other function call, and thus a new stack frame is created. Accessing the same (named) variable from within different stack frames will (because, as said, the access is using a relative address) thus access a different entities.

[Note: I hope this rather rough descriptions helps you, this is a topic that is - when talked about in depth - extremely depending on actual implementations (compilers), used optimizations, calling convention, operating system, target architecture, ... ]

I put together a simple stupid example, which hopefully shows that what you want to do should be possible, given that you appropriately free whatever you allocated:

unsigned int crazy_factorial(unsigned int const * const n) {
    unsigned int result;
    if (*n == 0) {
        result = 1;
    } else {
        unsigned int * const nextN = malloc(sizeof(unsigned int));
        *nextN = *n - 1;
        result = *n * crazy_factorial(nextN);
        free(nextN);
    }
    return result;
}

Running this with some output shows what's going on.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63