Memory allocation problems.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 22/05/2003 at 20:00, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   7- 8.100 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hi
    We have been having some really tricky crashes in a plugin we are working on.  It seems like it is related to STL memory allocation.  Does anyone know if there is a conflict between C4D and the Standard Template Library's memory allocation?  Have the Maxon developers replaced the C++ global memory allocator?
    Thanks ... any ideas would be appreciated.
    > -- Skyler



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 23/05/2003 at 02:28, xxxxxxxx wrote:

    Yes, this is a problem with all global memory allocations. The runtime allocates global objects before the C4DOS connection has been initialized.
    This isn't official advice yet, but what I did in one of my own plugins that needed global objects was to modify the internal glue of the API in c4d_pmain.cpp.
    You have to modify pmain.cpp like this:

        
        
        // this is the "glue" to C4D...  
        // please modify only if you know exactly what you are doing...
        
        
        
        
        #ifdef WIN32  
          #include <windows.h>  
        #endif
        
        
        
        
        #include "c4d_plugin.h"
        
        
        
        
        #ifdef __MAC  
          #ifdef __cplusplus  
          extern "C" {  
          #endif
        
        
        
        
          extern void __sinit(void);  
          extern void __destroy_global_chain(void);  
              
          #define C4D_MAIN LONG c4d_main(LONG action, void* p1, void* p2, void* p3)  
          C4D_MAIN;
        
        
        
        
          #ifdef __cplusplus  
          }  
          #endif  
        #else  
          #ifdef __PC  
            #ifdef __cplusplus  
            extern "C" {  
            #endif  
              
            #define C4D_MAIN LONG __declspec(dllexport) c4d_main(LONG action, void* p1, void* p2, void* p3)  
            C4D_MAIN;  
            
            /*BOOL APIENTRY DllMain(HANDLE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)  
            {  
              <remove>  
            }*/
        
        
        
        
            extern BOOL APIENTRY _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);  
            static HINSTANCE g_hinstDLL;  
            static LPVOID g_lpReserved;
        
        
        
        
            BOOL APIENTRY DllMainCRTStartup( HINSTANCE hinst, DWORD reason, LPVOID reserved )  
            {       
              g_hinstDLL = hinst;  
              g_lpReserved = reserved;  
              return TRUE;  
            }
        
        
        
        
            #ifdef __cplusplus  
            }  
            #endif  
          #else  
            #error "Unsupported OS"  
          #endif  
        #endif
        
        
        
        
        LONG InitOS(void *p);
        
        
        
        
        CHAR path_storage[1024];
        
        
        
        
        C4D_MAIN //(LONG action, void* p1, void* p2, void* p3)  
        {  
          static LONG init_count = 0;  
          LONG i;  
          CHAR *c;  
            
          switch (action)  
          {  
            case C4DPL_INIT_VERSION:  
              return C4DPL_VERSION;
        
        
        
        
            case C4DPL_INIT_SYS:  
              init_count += 1;  
              if (init_count == 1)  
              {  
                if (InitOS(p1) < 7500) return C4DPL_ERROR_VERSION;  
                #ifdef __PC  
                  _CRT_INIT(g_hinstDLL, DLL_PROCESS_ATTACH, g_lpReserved);  
                #endif  
                #ifdef __MAC  
                  __sinit();  
                #endif  
                if (!p3) return C4DPL_ERROR_VERSION;  
                for (i = 0, c = (CHAR* )p3; c[i]; i++) path_storage[i] = c[i];  
                path_storage[i] = 0;  
              }  
              return 1;
        
        
        
        
            case C4DPL_MESSAGE:  
              if (!PluginMessage((LONG)p1,p2)) return C4DPL_ERROR;  
              return 1; 
        
        
        
        
            case C4DPL_INIT:  
              return PluginStart();  
              
            case C4DPL_END:  
              init_count -= 1;  
              if (init_count == 0)  
              {  
                PluginEnd();  
                void FreeResource();  
                FreeResource();  
                #ifdef __PC  
                  _CRT_INIT(g_hinstDLL, DLL_PROCESS_DETACH, g_lpReserved);  
                #endif  
                #ifdef __MAC  
                  __destroy_global_chain();  
                #endif  
              }  
              return 1;  
                
            default:  
              break;  
          } 
        
        
        
        
          return C4DPL_ERROR;  
        }
    

    One also must add /ENTRY:DllMainCRTStartup to the linker options to make it link.
    This way you defer the call to _CRT_INIT(), which allocates all globals, until after the C4DPL_INIT_SYS message.
    Note: I have used and tested this myself, but there's no guarantee that it is 100 % safe, or that it will work with future versions. I'll remind the programmers to look into this again so that the above can perhaps be incorporated into official future versions.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 23/05/2003 at 05:08, xxxxxxxx wrote:

    Hmm, I'm not sure I fully understand this issue, and it seems rather important...

    Is this what you are saying:

    You cannot safely use any global (or static?) objects in your plugins, _unless_ you make the above (unofficial) modification to 'c4d_pmain.cpp'.

    Does this mod work for both Mac and PC?

    Also, are there any other issues like this that we should be aware of; i.e. things that are valid C++ but that we shouldn't use for plugins?

    Cheers - Steve



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 23/05/2003 at 08:33, xxxxxxxx wrote:

    Yes, you're right, and it can be very inconvenient. (Thus I always do the modification... :-) Afaik it only affects PC though, since the Mac part already has its _sinit() where I added _CRT_INIT() above. So that is yes, with the mod you're safe on both Mac and PC.
    The issue has been reported as a bug and will hopefully be fixed in the future. (I.e. officially fixed.)
    As for C++ features, I wouldn't recommend using any kind of exceptions without carefully catching them yourself, since the API isn't written with exceptions or exception safety in mind. And of course advanced templates are out as long as MSVC is the supported PC platform. (Getting better in MSVC 7, I guess.) Finally you cannot make virtual calls between two different plugin modules, since they don't share the same memory space. I don't think there's much more that's disallowed, though there are many parts of for example <iostream> that aren't very useful in a plugin.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 23/05/2003 at 08:52, xxxxxxxx wrote:

    Ok, thanks for the info.

    Cheers - Steve



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 27/05/2003 at 11:39, xxxxxxxx wrote:

    Mikael,
    I implemented your changes, but I'm still getting an STL memory cleanup crash. However, we are still using the version 7 API, I noticed your code was for version 8. Will your solution work in v7? I did add the entry into the linker options, and I copied the code straight from your post.
    Thanks,
    Jane
    Darkling Simulations



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 28/05/2003 at 00:01, xxxxxxxx wrote:

    I haven't tested it in R7, but I guess it should work. Could you place breakpoints at these locations and see what happens?

    • At the two _CRT_INIT() calls in c4d_pmain.cpp.
    • In the operator new and operator delete in c4d_memory.cpp.
    • In DLLMainCRTStartup(), to see that it's called.

    If the hack has worked there should be no allocation before the first _CRT_INIT(). Otherwise C4DOS is probably NULL in the first allocation. Or the other way around if it's during cleanup.
    Also you can see if the crash happens without STL but with a simple global static String somewhere in the code.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 28/05/2003 at 20:28, xxxxxxxx wrote:

    I put the breakpoints in as you suggested, and it behaved properly. Perhaps the problem is that our plug-in links to our own compiled libraries? It is in these libraries that the crashes occur. They still call C4D's memory functions.
    We tried actually commenting out the new and delete functions in c4d_memory.cpp. This got rid of the crash, but there was some strange behavior, and it was extremely slow.
    Instead, I restored new and delete and bypassed use of the STL vectors of STL strings. Oh well.
    Jane
    Darkling Simulations


Log in to reply