Board index » cppbuilder » ofstream access violation (TeamB to the rescue?)
Eike Petersen
![]() CBuilder Developer |
ofstream access violation (TeamB to the rescue?)2007-01-04 09:20:57 AM cppbuilder34 Hi, a long time ago I ran into a problem with the use of "atexit" in conjunction with dynamically loading *and* freeing a DLL at runtime. Recently I ran into a similar problem - again in conjunction with dynamically loading and freeing a DLL. Just like in your case after using the streaming facilities of the standard library and freeing the DLL at runtime, the program crashes at program termination *after* leaving WinMain(). I know there is an error with "atexit" in the Borland implementation of the C-Library which still is not fixed (see my old thread). It's quite possible the current problems have a similar cause. Old thread: groups.google.de/group/borland.public.cppbuilder.language/browse_frm/thread/460b7e2b16137dc/0e5f32b8e1aeb028&q=&rnum=1&hl=de#0e5f32b8e1aeb028 It seems that some programmer at Borland tried to do something about the problem, but after inspecting the source code of the RTL I'm under the impression he didn't get to finish his job. In source "startupd.c" you will find several references to a mysterious variable called "_multidll". I didn't quite figure out how exactly the mechanism is supposed to work, but I'm quite sure it doesn't work. In line 159 the code reads something like this: *** SNIP *** if (_multidll && (share__dll_table = _create_shmem()) != NULL && share__dll_table->table[share__dll_table->ntables] != (MODULE_DATA *)-1) { share__dll_table->table[share__dll_table->ntables++] = mod_table; } else { _multidll = 0; /* set a flag that will force the termination routine to call all of the exit procs. */ /* Call all of the _INIT_ functions. */ _init_exit_proc(&_dll_table, 0); } *** SNAP *** To my very surprise the implementation of the function '_create_shmem()' looks like this: *** SNIP ** MULTI_INIT *_create_shmem(void) { return NULL; } *** SNAP *** When the program shuts down the following code from source 'startupd.c' starting at line 229 will execute: *** SNIP /* The following loop calls the DLL's exit procedures. * This is also done by _cleanup(), if the application exits * with exit(); in that case, we won't do anything here, because * all the exit procedures will be marked as "called". But if the * application exits some other way, we must call the exit * procedures here. */ if (!_multidll) { /* First call all entries in the atexit table for this DLL. */ if (__pCallatexitProcs) __pCallatexitProcs(); /* Then call all of the _EXIT_ functions. */ _init_exit_proc(&_dll_table, 1); #if defined(__MT__) #if 0 /* Adding these two lines fixes a rare CG RTL memory leak. It's commented out since it seems to adversly affect other parts of the stream locking system. */ _cleanup_handle_locks(); _cleanup_stream_locks(); #endif /* 0 */ #endif /* __MT__ */ } *** SNAP *** As you can see the magic variable '_multidll' seems to be used here again - however it will always be zero because '_create_shmem' will always return NULL and therefore '_multidll' will always be reset to zero in the else branch of the initialization quoted above. Maybe I'm all on the wrong track, but something is definitely odd here. Maybe the code for destroying certain static objects *within the RTL* gets called twice? I'm not sure. The last time I spent over 8 hours debugging the RTL, but I had to turn my attention back to my real project. Best Regards Eike Petersen Fraser Ross wrote: QuoteI have a function in a DLL module that I've reduced to simply creating a |