Workaround for Memoryleaks
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 18/01/2009 at 14:54, xxxxxxxx wrote:
User Information:
Cinema 4D Version: 11
Platform:
Language(s) : C++ ;---------
Hi!How everyone should know, its possible to see memory leaks with the help of the 'c4d_debug.txt' file - very useful help but you only get linenumbers and filenames you don't know so its very hard to see which object wasn't freed.
>
\> ge_container.cp, Line 1377 -> 32 Bytes at 0x0x119998820! \> ge_container.cp, Line 1377 -> 32 Bytes at 0x0x1199988b0! \> ge_container.cp, Line 1377 -> 32 Bytes at 0x0x1199989d0! \> ge_container.cp, Line 1377 -> 32 Bytes at 0x0x119998b80! \> ge_container.cp, Line 1377 -> 32 Bytes at 0x0x119998790! \> ge_container.cp, Line 1377 -> 32 Bytes at 0x0x119998ca0! \> ge_container.cp, Line 1377 -> 32 Bytes at 0x0x119999000! \> ge_container.cp, Line 540 -> 16 Bytes at 0x0x119998c10! \> ge_container.cp, Line 1377 -> 32 Bytes at 0x0x119998d30! \> pluginlayer.cpp, Line 229 -> 32 Bytes at 0x0x1199992d0! \> register.cpp, Line 65 -> 1296 Bytes at 0x0x10f5fd6a0! \>
So I thought about my own solution to get a better summary about memory leaks in my plugin. Maybe this is already implemented in the c4dsdk, but all the other developers I asked, didn't know that and maybe it can help - especially for beginners. This is the output of my small workaround, if an object was not freed.
>
\> Memory Leak '0x10ec7b6a0', Line 143 in: /Applications/MAXON/c4dr11/plugins/my_plugin/source/main.cpp \> Memory Leak '0x10ee7b5b2', Line 543 in: /Applications/MAXON/c4dr11/plugins/my_plugin/source/test.cpp \>
This output is very similar to the cinema 4d output, but the difference is, you really have your path and linenumber of your project where the object was not freed.
This output is much more effective, isn't it? I guess, for experienced developers its 'an old shoe' but for me, it is a workaround I never thought about before. Especially for beginners it might be a good way to see what went wrong in the code. Here is a small example.
>
\> Vector \*vec; \> Bool PluginStart() \> { \> BaseObject \*obj = BaseObject::Alloc(Ocube); \> trace(obj); // see if this object is freed \> \> vec = gNew Vector; \> trace(obj); \> \> BaseBitmap \*bmp = BaseBitmap::Alloc(); \> trace(bmp); \> } \> \> void PluginEnd() \> { \> del_ptr(vec); //write this BEFORE you delete the object \> gDelete(vec); \> // del_ptr(vec); #WRONG! don't call it after you freed it \> PrintOut_MemoryResult(); //print out the summary to the console \> } \>
>
\> Output: \> Memory Leak '0x10ec430ea', Line 4 in: /Applications/MAXON/c4dr11/plugins/my_plugin/source/main.cpp \> Memory Leak '0x10c99283b', Line 10 in: /Applications/MAXON/c4dr11/plugins/my_plugin/source/main.cpp \>
Just copy and paste the following code to your project.
>
\> //state: not verified \> // leak_check.cpp \> // Author: Sebastian Rath (c) 2009 \> #ifdef \__DEBUGGING\_\_ \> #include "leak_check.h" \> \> \> GeAutoDynamicArray<ptr_addr> param_heap; \> GeAutoDynamicArray<void\*> ptr_heap; \> void SetPointer(void\* p, LONG v, CHAR\* c) \> { \> ptr_heap.Push(p); \> param_heap.Push(ptr_addr(v, c)); \> } \> \> void DelPointer(void\* p, LONG v, CHAR\* c) \> { \> LONG x = ptr_heap.Find(p); \> if(x==-1) printf("An error occured at line %i in file %s\n", v, c); \> ptr_heap.Remove(x,1); \> param_heap.Remove(x, 1); \> } \> \> #endif \> void PrintOut_MemoryResult() \> { \> #ifdef \__DEBUGGING\_\_ \> if( param_heap.count==0 ) \> { \> printf("Done! No memory leak found\n"); \> return; \> } \> \> for( LONG i=0; i< param_heap.count ; i++ ) \> { \> if(param_heap[i].line!=0) \> printf("Memory Leak '%p', Line %i in: %s\n", ptr_heap[i], param_heap[i].line, param_heap[i].fn); \> } \> #endif \> } \>
and this header file here:
>
\> //state: not verified \> //file leak_check.h \> // Author: Sebastian Rath (c) 2009 \> \> #ifndef LeakChecker \> #define LeakChecker \> \> #ifdef \__DEBUGGING\_\_ \> #include "ge_dynamicarray.h" \> typedef struct iptr_addr { \> iptr_addr() : line(-1), fn("failed") {}; \> iptr_addr(LONG lin, CHAR \*f) : line(lin), fn(f) {}; \> LONG line; \> CHAR \*fn; \> }ptr_addr; \> \> void SetPointer(void\* p, LONG v, CHAR\* c); \> void DelPointer(void\* p, LONG v, CHAR\* c); \> extern GeAutoDynamicArray<void\*> ptr_heap; \> extern GeAutoDynamicArray<ptr_addr> param_heap; \> #define trace(op) {SetPointer(op, (LONG)\__LINE\_\_, \__FILE\_\_);} \> \> #define del_ptr(op) { DelPointer(op, (LONG)\__LINE\_\_, \__FILE\_\_);} \> #else \> #define trace(op) \> #define del_ptr(op) \> #endif \> \> void PrintOut_MemoryResult(); \> \> #endif \>
If this code has a bug or something is fatal, pleas tell me.