0

I am not sure why Valgrind is reporting memory leak on it?

Pseudocode in .c file:

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 char* str_alloc(char *str) {
   char* dup = (char*) malloc((strlen(str) + 1) * sizeof(char));
   strcpy((char*) dup, (char*) str);
   return dup;
 }

 void function_c(char **name) {
   int len = 10;
   (void) realloc(*name, 100);
 }

 void function_b(char **name) {
   (void) function_c(name);
 }

 void function_a(char **name) {
   (void) function_b(name);
 }

 int main() {
   char* name = str_alloc("");
   function_a(&name);
   // Do something with name
   free(name);
 }

I am ignoring the value of realloc since I am kind of sure that realloc will always be on same pointer. Allocating/Reallocating from my own memory pool which is quite huge.

Of course, I can not write the code for memory pool here.

So, In what cases shall I expect to come as Valgrind leak? Couple of cases which I thought of:

  • If realloc happens to smaller memory. realloc is guaranteed to take care of it.
  • If realloc fails, then it is supposed to be memory leak. I understand this.

Any other cases?

halfer
  • 19,824
  • 17
  • 99
  • 186
Hemant Bhargava
  • 3,251
  • 4
  • 24
  • 45

2 Answers2

3

There is memory leak because you are loosing the memory allocated by realloc.

Syntax for realloc goes as below.

void *realloc(void *ptr, size_t size); 

Note: It is not guaranteed that pointer returned by the realloc will be same as old pointer passed to realloc and one should not depend on it.

Even compiler is also warning you about the same.

warning: ignoring return value of ‘realloc’, declared with attribute warn_unused_result [-Wunused-result]

(void) realloc(*name, 100);
^

Hence you need to modify your function_c function as below.

 void function_c(char **name) 
 {
     char *newPtr = NULL;
     newPtr  =  realloc(*name, 100);
     *name = newPtr;
 }
kiran Biradar
  • 12,700
  • 3
  • 19
  • 44
2

I am ignoring the value of realloc since I am kind of sure that realloc will always be on same pointer. Allocating/Reallocating from my own memory pool which is quite huge.

In code that uses the standard malloc/realloc/free interface, you simply cannot make this assumption, even if you think you provided the implementation and you know how it will behave under controlled conditions. Future people working on your code (including yourself, years from now after you've forgotten the details of this project) will assume there's nothing special about how your code uses standard interfaces and they can move the code onto an entirely different C implementation without bringing your special malloc library along.

Also, the C library is entitled to refuse to let you replace these functions, which is what's causing your immediate problem: valgrind forcibly substitutes its own implementation of malloc/realloc/free for whatever you had, an implementation that never returns the same pointer from realloc. This is on purpose, to catch bugs like this one.

If you want to implement a memory pool that makes guarantees such as "resizing an allocation does not move the allocation", then you need to give all of the functions new names (e.g. pool_alloc, pool_resize, pool_free).

zwol
  • 135,547
  • 38
  • 252
  • 361
  • Thanks. Valgrind comment make sense to me and clear up my doubts about the same. I do have my own implementations of malloc, calloc and realloc. – Hemant Bhargava Sep 24 '18 at 15:03
  • @HemantBhargava "valgrind forcibly substitutes its own implementation" is just an example of what might go wrong. The important sentence in this answer is the first one: "In code that uses the standard malloc/realloc/free interface, you simply cannot make this assumption." It does not need extra emphasis, because it is already the first sentence. – zwol Sep 25 '18 at 13:16