Hi,
I have encountered problems with a DLL earlier in my work, but now I
like to get some clarify about the issue.
The DLL contains implemented functions in the header and the tests
showed me, that the client get their own
versions of these 'inline' functions.
The code crashes in the actual setup of the code (with USE_HEADERCODE
defined) while DllMain tries to delete
the instance that was created in main().
First: Why does it crash, isn't the context of main the outer and the
DLL can access to the clients code (aka callback)?
It doesn't seem to be possible. I know, that I shouldn't do that, but
I haven't expected trouble with the destructor. I more likely
expected trouble with the inline function issue, as this is what I am
try to reproduce in my sample.
Second: I do actually not use MSVC++ compiler, but I got told inline
functions in headers of DLL's are not a problem with MSVC.
Is that true?
I at least expect problems, if there is a second DLL version that is
API compatible, but the logic in such inline functions have been
changed. This is because I have tested the code and indeed it has an
implementation in the client and DLL, thus they probably get
out of sync.
Third: Is there any clear statement about NOT doing inline functions
(header based functions) when creating a DLL?
I have tested my code now with MSVC 2005 and in parallel with Open
Watcom. MSVC doesn't have inline function implementations in client,
because the messages don't indicate this. But the Open Watcom compiler
does.
I assume that MSVC does it correctly, but can it be a feature not to
do it like MSVC, or is it then a bug in OW?
Output of MSVC:
C:\DLLIssue>DllIssue
*******************
* DllMain called. *
*******************
DLL statically loaded.
test::test() called.
String was: test::test() called.
test::doInline() called from dll.
********************
* DllMain leaving. *
********************
test::test() called.
test2::test2() called from dll.
Client:
String was: test2::test2() called from dll.
test::doInline() called from dll.
Client:
test::doNotInline() called.
Client:
test::callInline() called.
String was: test::doInline() called from dll.
test::doInline() called from dll.
Client:
String was: test::doInline() called from dll.
test::doInline() called from dll.
test::~test() called.
The string is: test::doInline() called from dll.
*******************
* DllMain called. *
*******************
DLL_PROCESS_DETACH for c:\dllissue\dll.cpp
DLL c:\dllissue\dll.cpp released by system.
String was: test::doInline() called from dll.
test::doInline() called from dll.
test2::~test2() called from dll.
The string is: test::doInline() called from dll.
test::~test() called.
The string is: test::doInline() called from dll.
DLL c:\dllissue\dll.cpp deleted test instance.
********************
* DllMain leaving. *
********************
C:\DLLIssue>
Output of Open Watcom:
C:\DLLIssue>DllIssue
*******************
* DllMain called. *
*******************
DLL statically loaded.
test::test() called.
String was: test::test() called.
test::doInline() called from dll.
********************
* DllMain leaving. *
********************
test::test() called.
test2::test2() called from client.
Client:
String was: test2::test2() called from client.
test::doInline() called from client.
Client:
test::doNotInline() called.
Client:
test::callInline() called.
String was: test::doInline() called from client.
test::doInline() called from dll.
Client:
String was: test::doInline() called from dll.
test::doInline() called from client.
test::~test() called.
The string is: test::doInline() called from dll.
*******************
* DllMain called. *
*******************
DLL_PROCESS_DETACH for dll.cpp
DLL dll.cpp released by system.
String was: test::doInline() called from client.
test::doInline() called from dll.
The instruction at 0x00401535 referenced memory at 0x00000000.
The memory could not be read.
Exception fielded by 0x00403770
EAX=0x0006fb88 EBX=0x00281bf0 ECX=0x0040b474 EDX=0x00000002
ESI=0x00000000 EDI=0x0006fc8c EBP=0x0006fc98 ESP=0x0006fbf8
EIP=0x00401535 EFL=0x00010217 CS =0x0000001b SS =0x00000023
DS =0x00000023 ES =0x00000023 FS =0x0000003b GS =0x00000000
Stack dump (SS:ESP)
0x00281bf0 0x00000074 0x0040151a 0x004012fd 0x003a0e30 0x00281815
0x00081008 0x003a0e30 0x0006fdf0 0x00080000 0x7c921483 0x7c98e120
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00192070 0x00000000 0x00281b93 0x00000001 0x00000000
0x00280000 0x00192070 0x002870f4 0x00280000 0x00000000 0x00000001
0x00283714 0x00280000 0x00000000 0x00000001 0x0006fcf4 0x00000000
0x0006fce8 0x00192070 0x7c91118a 0x00280000 0x00000000 0x00000001
0x00192070 0x00000000 0x001921c8 0x0006fd78 0x7c933ada 0x00281fa2
0x00280000 0x00000000 0x00000001 0x00000000 0x7c91de6e 0x00000000
C:\DLLIssue>
#include <dll.h>
#include <stdio.h>
int main() {
test* t = new test2();
cout << "Client:" << endl;
t->doInline();
cout << "Client:" << endl;
t->doNotInline();
cout << "Client:" << endl;
t->callInline();
cout << "Client:" << endl;
t->doInline();
// When no inline functions are declared then I can delete the
object created in the main function from the DLL at DllMain.
// But not if inline is used.
passObject(t);
//deleteObject();
getchar();
}
Here is the header:
/*
* If this define is active, the object is passed to the DLL and is
not deleted in the main function,
* then it will crash at DLL unload.
*/
#define USE_HEADERCODE
#ifndef __WATCOMC__
#include <iostream>
using namespace std;
#endif
#ifdef __WATCOMC__
#include <iostream.h>
#endif
#ifndef DLL_MODULE
#define DLLEXPORT __declspec(dllimport)
#endif
#ifdef DLL_MODULE
#define DLLEXPORT __declspec(dllexport)
#endif
#ifndef DLL_INCLUDE
#define DLL_INCLUDE
class DLLEXPORT test {
public:
test();
virtual ~test();
#ifdef USE_HEADERCODE
void doInline() {
cout << "String was: " << str << endl;
#ifndef DLL_MODULE
str="test::doInline() called from client.";
cout << str << endl;
#endif
#ifdef DLL_MODULE
str="test::doInline() called from dll.";
cout << str << endl;
#endif
}
#endif
#ifndef USE_HEADERCODE
void doInline();
#endif
void doNotInline();
void callInline();
protected:
char* str;
};
class DLLEXPORT test2 : public test {
public:
#ifdef USE_HEADERCODE
test2() {
#ifndef DLL_MODULE
str = "test2::test2() called from client.";
cout << "test2::test2() called from client." << endl;
#endif
#ifdef DLL_MODULE
str = "test2::test2() called from dll.";
cout << "test2::test2() called from dll." << endl;
#endif
}
virtual ~test2() {
#ifndef DLL_MODULE
cout << "test2::~test2() called from client." << endl;
cout << "The string is: " << str << endl;
#endif
#ifdef DLL_MODULE
cout << "test2::~test2() called from dll." << endl;
cout << "The string is: " << str << endl;
#endif
}
virtual void doInline() {
cout << "String was: " << str << endl;
#ifndef DLL_MODULE
str="test2::doInline() called from client.";
cout << str << endl;
#endif
#ifdef DLL_MODULE
str="test2::doInline() called from dll.";
cout << str << endl;
#endif
}
#endif
#ifndef USE_HEADERCODE
test2();
virtual ~test2();
void doInline();
#endif
};
DLLEXPORT test* getInstance();
DLLEXPORT test* getInstance2();
DLLEXPORT void passObject(test* _t);
DLLEXPORT void deleteObject();
#endif
Here is the cpp file of the DLL:
#include <dllmodule.h>
#include <dll.h>
#include <windows.h>
test* t = NULL;
DLLEXPORT test* getInstance() {
if (t == NULL) t = new test();
t->doInline();
return t;
}
DLLEXPORT test* getInstance2() {
if (t == NULL) t = new test2();
t->doInline();
return t;
}
DLLEXPORT void passObject(test* _t) {
if (t != NULL) delete t;
t = _t;
}
DLLEXPORT void deleteObject() {
cout << "void deleteObject() called." << endl;
if (t != NULL) {
t->doInline();
delete t;
t = NULL;
}
}
test::test() {
str = "test::test() called.";
cout << "test::test() called." << endl;
}
test::~test() {
cout << "test::~test() called." << endl;
cout << "The string is: " << str << endl;
}
void test::doNotInline() {
cout << "test::doNotInline() called." << endl;
}
void test::callInline() {
cout << "test::callInline() called." << endl;
doInline();
}
#ifndef USE_HEADERCODE
void test::doInline() {
cout << "String was: " << str << endl;
#ifndef DLL_MODULE
str="test::doInline() called from client.";
cout << str << endl;
#endif
#ifdef DLL_MODULE
str="test::doInline() called from dll.";
cout << str << endl;
#endif
}
#endif
#ifndef USE_HEADERCODE
test2::test2() {
str = "test::test() called.";
cout << "test::test() called." << endl;
}
test2::~test2() {
cout << "test::~test() called." << endl;
cout << "The string is: " << str << endl;
}
void test2::doInline() {
cout << "String was: " << str << endl;
#ifndef DLL_MODULE
str="test2::doInline() called from client.";
cout << str << endl;
#endif
#ifdef DLL_MODULE
str="test2::doInline() called from dll.";
cout << str << endl;
#endif
}
#endif
BOOL WINAPI DllMain(HINSTANCE dllHandle, DWORD reason, LPVOID
situation) {
char buf[100]="";
cout << "*******************" << endl;
cout << "* DllMain called. *" << endl;
cout << "*******************" << endl;
switch (reason) {
case DLL_PROCESS_ATTACH:
if (situation) {
cout << "DLL statically loaded." <<
endl;
}
else {
cout << "DLL dynamically loaded." <<
endl;
}
if (t == NULL) t = new test();
t->doInline();
break;
case DLL_THREAD_ATTACH:
cout << "New thread starting." << endl;
break;
case DLL_PROCESS_DETACH:
cout << "DLL_PROCESS_DETACH for " << __FILE__
<< endl;
if (situation)
{
cout << "DLL " << __FILE__ << "
released by system." << endl;
}
else
{
cout << "DLL " << __FILE__ << "
released by program." << endl;
}
if (t != NULL) {
t->doInline();
delete t;
cout << "DLL " << __FILE__ << " deleted
test instance." << endl;
}
break;
case DLL_THREAD_DETACH:
cout << "Thread terminating.\n" << endl;
default:
return FALSE;
}
cout << "********************" << endl;
cout << "* DllMain leaving. *" << endl;
cout << "********************" << endl;
return TRUE;
}
|
|
0
|
|
|
|
Reply
|
lothar.behrens (95)
|
12/2/2009 2:32:45 PM |
|
On 2 Dez., 15:32, Lothar Behrens <lothar.behr...@lollisoft.de> wrote:
> Hi,
>
> I have encountered problems with a DLL earlier in my work, but now I
> like to get some clarify about the issue.
>
> The DLL contains implemented functions in the header and the tests
> showed me, that the client get their own
> versions of these 'inline' functions.
>
> The code crashes in the actual setup of the code (with USE_HEADERCODE
> defined) while DllMain tries to delete
> the instance that was created in main().
>
> First: Why does it crash, isn't the context of main the outer and the
> DLL can access to the clients code (aka callback)?
>
> It doesn't seem to be possible. I know, that I shouldn't do that, but
> I haven't expected trouble with the destructor. I more likely
> expected trouble with the inline function issue, as this is what I am
> try to reproduce in my sample.
>
> Second: I do actually not use MSVC++ compiler, but I got told inline
> functions in headers of DLL's are not a problem with MSVC.
> Is that true?
>
> I at least expect problems, if there is a second DLL version that is
> API compatible, but the logic in such inline functions have been
> changed. This is because I have tested the code and indeed it has an
> implementation in the client and DLL, thus they probably get
> out of sync.
>
> Third: Is there any clear statement about NOT doing inline functions
> (header based functions) when creating a DLL?
>
> I have tested my code now with MSVC 2005 and in parallel with Open
> Watcom. MSVC doesn't have inline function implementations in client,
> because the messages don't indicate this. But the Open Watcom compiler
> does.
>
> I assume that MSVC does it correctly, but can it be a feature not to
> do it like MSVC, or is it then a bug in OW?
>
> Output of MSVC:
>
> C:\DLLIssue>DllIssue
> *******************
> * DllMain called. *
> *******************
> DLL statically loaded.
> test::test() called.
> String was: test::test() called.
> test::doInline() called from dll.
> ********************
> * DllMain leaving. *
> ********************
> test::test() called.
> test2::test2() called from dll.
> Client:
> String was: test2::test2() called from dll.
> test::doInline() called from dll.
> Client:
> test::doNotInline() called.
> Client:
> test::callInline() called.
> String was: test::doInline() called from dll.
> test::doInline() called from dll.
> Client:
> String was: test::doInline() called from dll.
> test::doInline() called from dll.
> test::~test() called.
> The string is: test::doInline() called from dll.
>
> *******************
> * DllMain called. *
> *******************
> DLL_PROCESS_DETACH for c:\dllissue\dll.cpp
> DLL c:\dllissue\dll.cpp released by system.
> String was: test::doInline() called from dll.
> test::doInline() called from dll.
> test2::~test2() called from dll.
> The string is: test::doInline() called from dll.
> test::~test() called.
> The string is: test::doInline() called from dll.
> DLL c:\dllissue\dll.cpp deleted test instance.
> ********************
> * DllMain leaving. *
> ********************
>
> C:\DLLIssue>
>
> Output of Open Watcom:
>
> C:\DLLIssue>DllIssue
> *******************
> * DllMain called. *
> *******************
> DLL statically loaded.
> test::test() called.
> String was: test::test() called.
> test::doInline() called from dll.
> ********************
> * DllMain leaving. *
> ********************
> test::test() called.
> test2::test2() called from client.
> Client:
> String was: test2::test2() called from client.
> test::doInline() called from client.
> Client:
> test::doNotInline() called.
> Client:
> test::callInline() called.
> String was: test::doInline() called from client.
> test::doInline() called from dll.
> Client:
> String was: test::doInline() called from dll.
> test::doInline() called from client.
> test::~test() called.
> The string is: test::doInline() called from dll.
>
> *******************
> * DllMain called. *
> *******************
> DLL_PROCESS_DETACH for dll.cpp
> DLL dll.cpp released by system.
> String was: test::doInline() called from client.
> test::doInline() called from dll.
> The instruction at 0x00401535 referenced memory at 0x00000000.
> The memory could not be read.
> Exception fielded by 0x00403770
> EAX=3D0x0006fb88 EBX=3D0x00281bf0 ECX=3D0x0040b474 EDX=3D0x00000002
> ESI=3D0x00000000 EDI=3D0x0006fc8c EBP=3D0x0006fc98 ESP=3D0x0006fbf8
> EIP=3D0x00401535 EFL=3D0x00010217 CS =3D0x0000001b SS =3D0x00000023
> DS =3D0x00000023 ES =3D0x00000023 FS =3D0x0000003b GS =3D0x00000000
> Stack dump (SS:ESP)
> 0x00281bf0 0x00000074 0x0040151a 0x004012fd 0x003a0e30 0x00281815
> 0x00081008 0x003a0e30 0x0006fdf0 0x00080000 0x7c921483 0x7c98e120
> 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
> 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
> 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
> 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
> 0x00000000 0x00192070 0x00000000 0x00281b93 0x00000001 0x00000000
> 0x00280000 0x00192070 0x002870f4 0x00280000 0x00000000 0x00000001
> 0x00283714 0x00280000 0x00000000 0x00000001 0x0006fcf4 0x00000000
> 0x0006fce8 0x00192070 0x7c91118a 0x00280000 0x00000000 0x00000001
> 0x00192070 0x00000000 0x001921c8 0x0006fd78 0x7c933ada 0x00281fa2
> 0x00280000 0x00000000 0x00000001 0x00000000 0x7c91de6e 0x00000000
>
> C:\DLLIssue>
>
> #include <dll.h>
> #include <stdio.h>
>
> int main() {
>
> =A0 =A0 test* t =3D new test2();
>
> =A0 =A0 cout << "Client:" << endl;
> =A0 =A0 t->doInline();
>
> =A0 =A0 cout << "Client:" << endl;
> =A0 =A0 t->doNotInline();
>
> =A0 =A0 cout << "Client:" << endl;
> =A0 =A0 t->callInline();
>
> =A0 =A0 cout << "Client:" << endl;
> =A0 =A0 t->doInline();
>
> =A0 =A0 // When no inline functions are declared then I can delete the
> object created in the main function from the DLL at DllMain.
> =A0 =A0 // But not if inline is used.
> =A0 =A0 passObject(t);
>
> =A0 =A0 //deleteObject();
>
> =A0 =A0 getchar();
>
> }
>
> Here is the header:
>
> /*
> =A0* If this define is active, the object is passed to the DLL and is
> not deleted in the main function,
> =A0* then it will crash at DLL unload.
> =A0*/
> #define USE_HEADERCODE
>
> #ifndef __WATCOMC__
> #include <iostream>
> using namespace std;
> #endif
>
> #ifdef __WATCOMC__
> #include <iostream.h>
> #endif
>
> #ifndef DLL_MODULE
> #define DLLEXPORT __declspec(dllimport)
> #endif
>
> #ifdef DLL_MODULE
> #define DLLEXPORT __declspec(dllexport)
> #endif
>
> #ifndef DLL_INCLUDE
> #define DLL_INCLUDE
>
> class DLLEXPORT test {
> public:
>
> =A0 =A0 test();
> =A0 =A0 virtual ~test();
> #ifdef USE_HEADERCODE
> =A0 =A0 void doInline() {
> =A0 =A0 =A0 =A0 cout << "String was: " << str << endl;
> #ifndef DLL_MODULE
> =A0 =A0 =A0 =A0 str=3D"test::doInline() called from client.";
> =A0 =A0 =A0 =A0 cout << str << endl;
> #endif
> #ifdef DLL_MODULE
> =A0 =A0 =A0 =A0 str=3D"test::doInline() called from dll.";
> =A0 =A0 =A0 =A0 cout << str << endl;
> #endif
> =A0 =A0 }
> #endif
>
> #ifndef USE_HEADERCODE
> =A0 =A0 void doInline();
> #endif
>
> =A0 =A0 void doNotInline();
>
> =A0 =A0 void callInline();
>
> protected:
>
> =A0 =A0 char* str;
>
> };
>
> class DLLEXPORT test2 : public test {
> public:
> #ifdef USE_HEADERCODE
> =A0 =A0 test2() {
> #ifndef DLL_MODULE
> =A0 =A0 =A0 =A0 str =3D "test2::test2() called from client.";
> =A0 =A0 =A0 =A0 cout << "test2::test2() called from client." << endl;
> #endif
> #ifdef DLL_MODULE
> =A0 =A0 =A0 =A0 str =3D "test2::test2() called from dll.";
> =A0 =A0 =A0 =A0 cout << "test2::test2() called from dll." << endl;
> #endif
> =A0 =A0 }
> =A0 =A0 virtual ~test2() {
> #ifndef DLL_MODULE
> =A0 =A0 =A0 =A0 cout << "test2::~test2() called from client." << endl;
> =A0 =A0 =A0 =A0 cout << "The string is: " << str << endl;
> #endif
> #ifdef DLL_MODULE
> =A0 =A0 =A0 =A0 cout << "test2::~test2() called from dll." << endl;
> =A0 =A0 =A0 =A0 cout << "The string is: " << str << endl;
> #endif
> =A0 =A0 }
>
> =A0 =A0 virtual void doInline() {
> =A0 =A0 =A0 =A0 cout << "String was: " << str << endl;
> #ifndef DLL_MODULE
> =A0 =A0 =A0 =A0 str=3D"test2::doInline() called from client.";
> =A0 =A0 =A0 =A0 cout << str << endl;
> #endif
> #ifdef DLL_MODULE
> =A0 =A0 =A0 =A0 str=3D"test2::doInline() called from dll.";
> =A0 =A0 =A0 =A0 cout << str << endl;
> #endif
> =A0 =A0 }
> #endif
>
> #ifndef USE_HEADERCODE
> =A0 =A0 test2();
> =A0 =A0 virtual ~test2();
> =A0 =A0 void doInline();
> #endif
>
> };
>
> DLLEXPORT test* getInstance();
> DLLEXPORT test* getInstance2();
>
> DLLEXPORT void passObject(test* _t);
> DLLEXPORT void deleteObject();
>
> #endif
>
> Here is the cpp file of the DLL:
>
> #include <dllmodule.h>
> #include <dll.h>
> #include <windows.h>
>
> test* t =3D NULL;
>
> DLLEXPORT test* getInstance() {
> =A0 =A0 if (t =3D=3D NULL) t =3D new test();
> =A0 =A0 t->doInline();
> =A0 =A0 return t;
>
> }
>
> DLLEXPORT test* getInstance2() {
> =A0 =A0 if (t =3D=3D NULL) t =3D new test2();
> =A0 =A0 t->doInline();
> =A0 =A0 return t;
>
> }
>
> DLLEXPORT void passObject(test* _t) {
> =A0 =A0 if (t !=3D NULL) delete t;
> =A0 =A0 t =3D _t;
>
> }
>
> DLLEXPORT void deleteObject() {
> =A0 =A0 cout << "void deleteObject() called." << endl;
> =A0 =A0 if (t !=3D NULL) {
> =A0 =A0 =A0 =A0 t->doInline();
> =A0 =A0 =A0 =A0 delete t;
> =A0 =A0 =A0 =A0 t =3D NULL;
> =A0 =A0 }
>
> }
>
> test::test() {
> =A0 =A0 str =3D "test::test() called.";
> =A0 =A0 cout << "test::test() called." << endl;
>
> }
>
> test::~test() {
> =A0 =A0 cout << "test::~test() called." << endl;
> =A0 =A0 cout << "The string is: " << str << endl;
>
> }
>
> void test::doNotInline() {
> =A0 =A0 cout << "test::doNotInline() called." << endl;
>
> }
>
> void test::callInline() {
> =A0 =A0 cout << "test::callInline() called." << endl;
> =A0 =A0 doInline();
>
> }
>
> #ifndef USE_HEADERCODE
> void test::doInline() {
> =A0 =A0 cout << "String was: " << str << endl;
> #ifndef DLL_MODULE
> =A0 =A0 str=3D"test::doInline() called from client.";
> =A0 =A0 cout << str << endl;
> #endif
> #ifdef DLL_MODULE
> =A0 =A0 str=3D"test::doInline() called from dll.";
> =A0 =A0 cout << str << endl;
> #endif}
>
> #endif
>
> #ifndef USE_HEADERCODE
> test2::test2() {
> =A0 =A0 str =3D "test::test() called.";
> =A0 =A0 cout << "test::test() called." << endl;
>
> }
>
> test2::~test2() {
> =A0 =A0 cout << "test::~test() called." << endl;
> =A0 =A0 cout << "The string is: " << str << endl;
>
> }
>
> void test2::doInline() {
> =A0 =A0 cout << "String was: " << str << endl;
> #ifndef DLL_MODULE
> =A0 =A0 str=3D"test2::doInline() called from client.";
> =A0 =A0 cout << str << endl;
> #endif
> #ifdef DLL_MODULE
> =A0 =A0 str=3D"test2::doInline() called from dll.";
> =A0 =A0 cout << str << endl;
> #endif}
>
> #endif
>
> BOOL WINAPI DllMain(HINSTANCE dllHandle, DWORD reason, LPVOID
> situation) {
> =A0 =A0 =A0 =A0 char buf[100]=3D"";
>
> =A0 =A0 =A0 =A0 cout << "*******************" << endl;
> =A0 =A0 =A0 =A0 cout << "* DllMain called. *" << endl;
> =A0 =A0 =A0 =A0 cout << "*******************" << endl;
>
> =A0 =A0 =A0 =A0 switch (reason) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case DLL_PROCESS_ATTACH:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (situation) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cout << "=
DLL statically loaded." <<
> endl;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cout << "=
DLL dynamically loaded." <<
> endl;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (t =3D=3D NULL) t =3D =
new test();
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 t->doInline();
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case DLL_THREAD_ATTACH:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cout << "New thread start=
ing." << endl;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case DLL_PROCESS_DETACH:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cout << "DLL_PROCESS_DETA=
CH for " << __FILE__
> << endl;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (situation)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cout << "=
DLL " << __FILE__ << "
> released by system." << endl;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cout << "=
DLL " << __FILE__ << "
> released by program." << endl;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (t !=3D NULL) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 t->doInline();
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 delete t;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cout << "DLL " <<=
__FILE__ << " deleted
> test instance." << endl;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case DLL_THREAD_DETACH:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cout << "Thread terminati=
ng.\n" << endl;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 default:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return FALSE;
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 cout << "********************" << endl;
> =A0 =A0 =A0 =A0 cout << "* DllMain leaving. *" << endl;
> =A0 =A0 =A0 =A0 cout << "********************" << endl;
>
> =A0 =A0 =A0 =A0 return TRUE;
>
>
>
> }
Here I have placed the project files to let you compare.
http://www.lollisoft.de/index.php?module=3Darticles&func=3Ddisplay&aid=3D8&=
ptid=3D10
|
|
0
|
|
|
|
Reply
|
Lothar
|
12/2/2009 2:59:17 PM
|
|
Here I have placed the project files and also it supports now
compiling with Visual Studio to let you compare.
http://www.lollisoft.de/index.php?module=articles&func=display&aid=8&ptid=10
|
|
0
|
|
|
|
Reply
|
Lothar
|
12/2/2009 3:01:07 PM
|
|
>> The code crashes in the actual setup of the code
>> (with USE_HEADERCODE
>> defined) while DllMain tries to delete
>> the instance that was created in main().
What kind of runtime library are you using? In MSVC you have a choice
of using a DLL version or a static version. It sounds like your
problem is what happens when a static version is used, since that
gives you different copies of the runtime lib in the exe and the
DLL.
When you use the static runtime lib you cannot allocate something from
one module and delete it in the other. You have to do the delete with
the exact same runtime that allocated.
If both exe and DLL use the same DLL runtime then this problem goes
away,
|
|
0
|
|
|
|
Reply
|
ScottMcP
|
12/4/2009 2:39:11 PM
|
|
On 4 Dez., 15:39, "ScottMcP [MVP]" <scott...@mvps.org> wrote:
> >> The code crashes in the actual setup of the code
> >> (with USE_HEADERCODE
> >> defined) while DllMain tries to delete
> >> the instance that was created in main().
>
> What kind of runtime library are you using? =A0In MSVC you have a choice
> of using a DLL version or a static version. =A0It sounds like your
> problem is what happens when a static version is used, since that
> gives you different copies of the runtime lib in the exe and the
> DLL.
>
> When you use the static runtime lib you cannot allocate something from
> one module and delete it in the other. =A0You have to do the delete with
> the exact same runtime that allocated.
>
> If both exe and DLL use the same DLL runtime then this problem goes
> away,
Yes on Open Watcom I have the same choice. Using the DLL version
solved the crash.
Thanks
|
|
0
|
|
|
|
Reply
|
Lothar
|
12/4/2009 4:00:34 PM
|
|
On 4 Dez., 15:39, "ScottMcP [MVP]" <scott...@mvps.org> wrote:
> >> The code crashes in the actual setup of the code
> >> (with USE_HEADERCODE
> >> defined) while DllMain tries to delete
> >> the instance that was created in main().
>
> What kind of runtime library are you using? =A0In MSVC you have a choice
> of using a DLL version or a static version. =A0It sounds like your
> problem is what happens when a static version is used, since that
> gives you different copies of the runtime lib in the exe and the
> DLL.
>
> When you use the static runtime lib you cannot allocate something from
> one module and delete it in the other. =A0You have to do the delete with
> the exact same runtime that allocated.
>
> If both exe and DLL use the same DLL runtime then this problem goes
> away,
But what is with my question about inline (or at least functions
implemented in header)?
It seems impossible for MSVC to create duplicates of inlined functions
in client and DLL
except not to export the class at all from the DLL.
That brings me to my assumption that MSVC deactivates inline for
exported classes. Right?
Thanks
Lothar
|
|
0
|
|
|
|
Reply
|
Lothar
|
12/4/2009 4:24:24 PM
|
|
|
5 Replies
191 Views
(page loaded in 0.144 seconds)
|