// JP opened flex table

Click to See Complete Forum and Search --> : DLL Global Object Constructor String Error


n00b3
June 29th, 2008, 07:54 PM
DLL Global Object Constructor String Error

Hello,

This one has really got my head spinning. I cannot figure it out.

I have a c++ console application that loads a dll.
In that dll there is a global variable that is a user defined object.
Upon the dll being loaded the dll calls the object constructor to instantiate the global variable (as expected).
In the constructor I try to use a const string which I have declared in an included file, but I get an error.
The error I recieve is a SIGSEGV, which to me usually means I am referencing an array past its bounds.

I have recreated this in the following simplified files. There are two projects 1) quickhook which calls the dll quickdll.dll, and 2) quickdll which is the dll loaded in quickhook.

quickhook's main.cpp

#include <iostream>
#include <windows.h>

using namespace std;

int main()
{

const string QUICKDLL_DLL = "E:\\C++\\codeblocks\\Practice\\quickdll\\bin\\Debug\\quickdll.dll";

if (!(hinstDLL = LoadLibrary((LPCTSTR)QUICKDLL_DLL.c_str()))) {
DWORD dwErr1 = ::GetLastError();
cout << "Loading Library Failed:" << dwErr1 << endl;
}

//OTHER CODE

return 0;
}


quickdll's main.cpp

#include "main.h"
#include <string>
#include "myclass.h"

using namespace std;

MyClass myclass;


quickdll's myclass.h

#ifndef MYCLASS_H_INCLUDED
#define MYCLASS_H_INCLUDED

#include <string>

using namespace std;

class MyClass {
public:
string str;
MyClass();
};

#endif // MYCLASS_H_INCLUDED


quickdll's myclass.cpp

#ifndef MYCLASS_CPP_INCLUDED
#define MYCLASS_CPP_INCLUDED

#include "myclass.h"
#include <string>
#include "const.h"

using namespace std;

MyClass::MyClass() {
this->str = USER_SN;
}

#endif // MYCLASS_CPP_INCLUDED


quickdll's const.h

#ifndef CONST_H_INCLUDED
#define CONST_H_INCLUDED

#include <string>

using namespace std;

//User Constant
const string USER_SN = "MEMEME";

#endif // CONST_H_INCLUDED


Here is the backtrace from,

#0 712CAD96 std::string::assign() (E:\C++\codeblocks\Practice\quickdll\bin\Debug\quickdll.dll:??)
#1 712CCD45 std::string::operator=() (E:\C++\codeblocks\Practice\quickdll\bin\Debug\quickdll.dll:??)
#2 712C1291 MyClass::MyClass(this=0x712d0030) (E:/C++/codeblocks/Practice/quickdll/myclass.cpp:12)
#3 712C1421 __static_initialization_and_destruction_0(__initialize_p=1, __priority=65535) (E:/C++/codeblocks/Practice/quickdll/main.cpp:9)
#4 712C1458 global constructors keyed to myclass() (E:/C++/codeblocks/Practice/quickdll/main.cpp:10)
#5 712C605F __do_global_ctors() (E:\C++\codeblocks\Practice\quickdll\bin\Debug\quickdll.dll:??)
#6 712C10E1 DllMainCRTStartup@12() (E:\C++\codeblocks\Practice\quickdll\bin\Debug\quickdll.dll:??)
#7 7C90118A ntdll!LdrSetAppCompatDllRedirectionCallback() (C:\WINDOWS\system32\ntdll.dll:??)
#8 712C0000 ??() (??:??)
#9 00000001 ??() (??:??)
#10 00000000 ??() (??:??)


When I debug this I get the sigsegv with the above back trace.

What is going on here? This one has me losing my hair... What "lesson" from programming 101 did I miss?

Thanks,

n00b3
June 29th, 2008, 09:41 PM
Hello,

I am using code::blocks with mingw32 gcc 3.4.5

I do not need a dll entry point to duplicate the error.

Also, I have replicated this with non-dll implementation.


#include <iostream>
#include "myclass.h"

using namespace std;

MyClass myclass;

int main()
{
cout << "Hello world!" << endl;
return 0;
}


Could this have to do with the "order" of instantiation. For instance, the string object has not been instantiated before the global MyClass object gets instantiated? I tried naming the MyClass ZyClass, b/c 'z' comes after 's', but this did not do anything. I am guessing my compiler loads up the MyClass stuff first b/c it is in the project root, and loads up the string stuff afterwards because it is not.
I am thinking this way because:
1) I do not experience this issue with built in c++ types such as 'int'.

const int USER_SN = 3;

2) I do not experience this issue with another user defined object

const MyClass2 USER_SN;

where,

class MyClass2 {
public:
int a;
MyClass2();
};

MyClass2::MyClass2() {
this->a = 34;
}


Honestly, I haven't a clue...

Paul McKenzie
June 29th, 2008, 11:04 PM
Hello,

I am using code::blocks with mingw32 gcc 3.4.5

I do not need a dll entry point to duplicate the error.Unless all global objects are declared in a single module, then the order of instantiation of global object declared in different modules is unspecified by the standard.

The reason why "int" and simple variables work is that these types do not have functions to initialize them (i.e. constructors). That is the major difference between 'C variables and C++ objects variables, and that is that C++ objects must have the constructor called by the runtime at some unspecified point in time before main() is called.

Regards,

Paul McKenzie

n00b3
June 29th, 2008, 11:11 PM
Thank you Paul. At least there is an answer now.

Now that I know it is 'unspecified' behavior that I am experiencing, I can stop going insane.

It is perhaps ironic that the unspecified behavior of the runtime has also made me behave in unspecified seemingly erratic ways too.

Arjay
June 30th, 2008, 08:18 AM
It is perhaps ironic that the unspecified behavior of the runtime has also made me behave in unspecified seemingly erratic ways too.Try adding a constructor - it worked for me. ;)

n00b3
June 30th, 2008, 02:15 PM
Hello,

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
explains it pretty well

I ended up changing


//const string USER_SN = "MEMEME";
const char USER_SN[] = "MEMEME";


Thanks for the responses

//JP added flex table