I cannot add to what others have said in terms of defining memory leaks, but I can give you some notes on when a memory leak can occur.
The first case that comes to mind is a function that performs the selection:
int* somefunction(size_t sz) { int* mem; mem = malloc(sz*sizeof(int)); return mem; }
There is nothing inherited in writing a function in this way. This is very similar to malloc. The problem is that you are starting now:
int* x = somefunction(5);
And itβs easy to forget, now itβs not malloc to free x. Again, there is nothing in it that means that you will forget, but my experience tells me that this is something that I and others do not notice.
A good strategy to get around this is to specify in a function calling this distribution. So, call somefunction_alloc function.
The second case that comes to mind is topics, especially fork() , because the code is all in one place. If you carefully code functions, several files, etc., you almost always avoid mistakes, but remember that everything should be free in some area, including those that were allocated both fork () and pre fork. Consider this:
int main() { char* buffer = malloc(100*sizeof(char)); int fork_result = fork(); if ( fork_result < 0 ) { printf("Error\n"); return 1; } elseif ( fork_result == 0 ) { return 0; } else { } free(buffer); return 0; }
There is a small mistake here. The parent will not skip any memory, but the child does this because it is an exact copy of the parent, including the heap, but it exits before freeing anything. Free should occur on both codes. Similarly, if the plug fails, you still will not be released. It's easy to miss something when you write such code. The best way is to create an exit code variable, for example int status = 0; , and change it where errors occurred, and not use the return in any structure, but allow the paths of the child and parent codes to continue until the end of the program, as they should.
However, threads and markup always make debugging more difficult due to their nature.