dll entry point question/advice needed - c++

I have a dynamic library of c++ code that is cross platform and mostly just native c++. I then use this dynamic library from my main exe. Up until now all has been good on OSX using gcc. Now I'm on windows I am confused as to what method I should use to enter the dll. I don't have a DllMain function at present as this wasn't required in gcc (to my knowledge). My initial tests worked but on inspection revealed that strangely one of my class constructors was being called on dll load, so I figured I needed to do something more on windows. So do I:
add a DllMain function?
am I safe to just use the noentry compiler option?
When I do either of the above I start getting compiler complaints in the vein of ".CRT section exists there may be unhandled static initializers or terminators"
I have read up on this using this article, but any advice and clarity on the best way forward would be greatly appreciated. Its all a bit blurry in my head as to what I need to do.

Based on the .CRT error, you definitely need a DllMain function. For most Windows compilers, a DllMain will be provided for you automatically, so that you don't need to write one yourself. Based on other parts of your question it seems most likely that you are using Visual C++, whose CRT does provide a DllMain for you. So while you do need a DllMain, you don't need to write the code for it.
The default VC CRT DllMain is used to initialize the CRT for the DLL in question, and to initialise all the static/global variables that the dll provides.
The model for DLLs on Unix and Windows is significantly different, and you should think of each DLL as having a more 'private' set of state. Although, if all Dlls opt into the same version of the CRT dll, some of that state will then be shared.
Because the CRT is providing a DllMain for you, you should not throw /noentry on the linker.
The .CRT section exists error (which you must have seen by throwing /noentry) is telling you that you need a DllMain because you've got one or more objects in your DLL that require static initialisation.
Martyn

If it is just a library, then NOENTRY should suffice. DllMain is there to control events that happen with the DLL (i.e. attach, detach etc).

You can change the code (slightly) to avoid all entry points but main. Essentially, if you have any variable defined outside of the functions (globally but not statically linked), wrap them in a function call. Use the often-forgotten static function variables.
Ie, change global declaration
SomeType var_name;
to this:
SomeType & var_name(){static SomeType var; return var;}
Similarly, you can change static class instance variables by changing this:
struct Container{
Container();
static Container instance;
};
Container Container::instance;
to this:
struct Container{
Container();
static Container & instance();
};
Container & Container::instance(){
static Container var;
return var;
}
This is essentially a singleton, but there might be some concurrency issues if the 1st time you access the instance will be from a multi-threaded environment. In fact, the thing to keep in mind is that unlike globally-defined variables, static locally-defined variables will be initialized the first time the function is called.

Related

C++ Passing std::string by reference to function in dll

I have the problem with passing by reference std::string to function in dll.
This is function call:
CAFC AFCArchive;
std::string sSSS = std::string("data\\gtasa.afc");
AFCER_PRINT_RET(AFCArchive.OpenArchive(sSSS.c_str()));
//AFCER_PRINT_RET(AFCArchive.OpenArchive(sSSS));
//AFCER_PRINT_RET(AFCArchive.OpenArchive("data\\gtasa.afc"));
This is function header:
#define AFCLIBDLL_API __declspec(dllimport)
AFCLIBDLL_API EAFCErrors CAFC::OpenArchive(std::string const &_sFileName);
I try to debug pass-by-step through calling the function and look at _sFileName value inside function.
_sFileName in function sets any value(for example, t4gs..\n\t).
I try to detect any heap corruption, but compiler says, that there is no error.
DLL has been compiled in debug settings. .exe programm compiled in debug too.
What's wrong?? Help..!
P.S. I used Visual Studio 2013. WinApp.
EDIT
I have change header of func to this code:
AFCLIBDLL_API EAFCErrors CAFC::CreateArchive(char const *const _pArchiveName)
{
std::string _sArchiveName(_pArchiveName);
...
I really don't know, how to fix this bug...
About heap: it is allocated in virtual memory of our process, right? In this case, shared virtual memory is common.
The issue has little to do with STL, and everything to do with passing objects across application boundaries.
1) The DLL and the EXE must be compiled with the same project settings. You must do this so that the struct alignment and packing are the same, the members and member functions do not have different behavior, and even more subtle, the low-level implementation of a reference and reference parameters is exactly the same.
2) The DLL and the EXE must use the same runtime heap. To do this, you must use the DLL version of the runtime library.
You would have encountered the same problem if you created a class that does similar things (in terms of memory management) as std::string.
Probably the reason for the memory corruption is that the object in question (std::string in this case) allocates and manages dynamically allocated memory. If the application uses one heap, and the DLL uses another heap, how is that going to work if you instantiated the std::string in say, the DLL, but the application is resizing the string (meaning a memory allocation could occur)?
C++ classes like std::string can be used across module boundaries, but doing so places significant constraints on the modules. Simply put, both modules must use the same instance of the runtime.
So, for instance, if you compile one module with VS2013, then you must do so for the other module. What's more, you must link to the dynamic runtime rather than statically linking the runtime. The latter results in distinct runtime instances in each module.
And it looks like you are exporting member functions. That also requires a common shared runtime. And you should use __declspec(dllexport) on the entire class rather than individual members.
If you control both modules, then it is easy enough to meet these requirements. If you wish to let other parties produce one or other of the modules, then you are imposing a significant constraint on those other parties. If that is a problem, then consider using more portable interop. For example, instead of std::string use const char*.
Now, it's possible that you are already using a single shared instance of the dynamic runtime. In which case the error will be more prosaic. Perhaps the calling conventions do not match. Given the sparse level of detail in your question, it's hard to say anything with certainty.
I encountered similar problem.
I resolved it synchronizing Configuration Properties -> C / C++ settings.
If you want debug mode:
Set _DEBUG definition in Preprocessor Definitions in both projects.
Set /MDd in Code Generation -> Runtime Library in both projects.
If you want release mode:
Remove _DEBUG definition in Preprocessor Definitions in both projects.
Set /MD in Code Generation -> Runtime Library in both projects.
Both projects I mean exe and dll project.
It works for me especially if I don't want to change any settings of dll but only adjust to them.

global static variable instantiation behaviour

My question is simple, maybe the answer is not.
In C++ (using Intel C++ 13.1 compiler on Win7) are global static variables always instantiated before main() is executed? If no, does it depends on the compile options (like /Ox)?
If they are declared and defined in DLL, is it the same?
Here is a case:
I have something like:
// in DLL.h
class MyClass
{
public:
MyClass();
};
static MyClass *sgMyClassPtr;
and
// in DLL.cpp
MyClass *sgMyClassPtr = new MyClass;
MyClass::MyClass()
{
// Code to execute here
}
Note that I omited the export declaration but it is correctly exported.
From my main application code, it seems that MyClass::MyClass() has not always been executed when I run it. I really don't understand but it looks like if the DLL had not been loaded yet or the static had not been correctly instantiated. Note that there is no threading and every call is synchronous (at least in my code!)
If you have any idea or suggestion, it will be appreciated. Thank you!
UPDATE 1
Maybe it will be easier if I tell you what I want to get rather than what I did...
I want to have a variable that is automatically instantiated at DLL load time. This variable will be registered (ptr stored in a std::set, say) by a singleton in the application (the .exe). The application singleton doesn't know about the DLL but the DLL knows the application singleton. So, on DLL load, I want the var to instantiate right now then registers itself in the application singleton. That is why I declared the var static inside the DLL and instantiated it there. The registration is done in the cTor.
My initial question was: does the static instantiation occurs right on DLL load or it may be delayed? I ask this question because sometimes I observe strange behaviours and it looks like an asynchronous problem... ???
The static initialisation occurs when the DLL is loaded, but depending on linker options, the DLL can be demand-loaded. Note that if you include the class in both the DLL and the main program but you don't export it from the DLL, then you'll get two copies of the code, and potentially two copies of your (class) static variables. So you might be getting confused by one copy not being initialised when the other one actually already has.
But make sure that you understand the linker options around lazy loading the DLLs first.

MSVCR and CRT Initialization

Out of curiosity, what exactly happens when an application compiled with the MSVCR is loaded, resp. how does the loader of Windows actually initialize the CRT? For what I have gathered so far, when the program as well as all the imported libraries are loaded into memory and all relocations are done, the CRT startup code (_CRT_INIT()?) initializes all global initializers in the .CRT$XC* sections and calls the user defined main() function. I hope this is correct so far.
But let's assume, for the sake of explanation, a program that is not using the MSVCR (e.g. an application built with Cygwin GCC or other compilers) tries to load a library at runtime, requiring the CRT, using a custom loader/runtime linker, so no LoadLibrary() involved. How would the loader/linker has to handle CRT initialization? Would it have to manually initialize all "objects" in said sections, does it have to do something else to make the internal wiring of the library work properly, or would it have to just call _CRT_INIT() (which unpractically is defined in the runtime itself and not exported anywhere as far as I am aware). Would this mix-up even work in any way, assuming that the non-CRT application and the CRT-library would not pass any objects, exceptions and things the like between them?
I would be very interested in finding out, because I can't quite make out what the CRT has an effect on the actual loading process...
Any information is very appreciated, thanks!
The entrypoint for an executable image is selected with the /ENTRY linker option. The defaults it uses are documented well in the MSDN Library article. They are the CRT entrypoint.
If you want to replace the CRT then either pick the same name or use the /ENTRY option explicitly when you link. You'll also need /NODEFAULTLIB to prevent it from linking the regular .lib
Each library compiled against the C++ runtime is calling _DllMainCRTStartup when it's loaded. _DllMainCRTStartup calls _CRT_INIT, which initializes the C/C++ run-time library and invokes C++ constructors on static, non-local variables.
The PE format contains an optional header that has a slot called 'addressofentrypoint', this slot calls a function that will call _DllMainCRTStartup which fires the initialization chain.
after _DllMainCRTStartup finishes the initialization phase it will call your own implemented DllMain() function.
When you learn about programming, someone will tell you that "the first thing that happens is that the code runs in main. But that's a bit like when you learn about atoms in School, they are fairly well organized and operate acorrding to strict rules. If you later go to a Nuclear/Particle Physics class at university, those simple/strict rules are much more detailed and don't always apply, etc.
When you link a C or C++ program the CRT contains some code something like this:
start()
{
CRT_init();
...
Global_Object_Constructors();
...
exit(main());
}
So the initialization is done by the C runtime library itself, BEFORE it calls your main.
A DLL has a DllMain that is executed by LoadLibrary() - this is responsible for initializing/creating global objects in the DLL, and if you don't use LoadLibrary() [e.g. loading the DLL into memory yourself] then you would have to ensure that objects are created and initialized.

Generate a List/Set by preprocessor/template from different modules and has to be filled before linking

I have some global variables (classes) that as I understand have created before main() call. I need some technique to add data to a List of something either global or as member of that class from any part of my code and it have to be filled before Linker. To use it inside globally created classes. Is it possible? I did not find any similar solution or even question, so any help will be appreciated.
Detailed example:
I've have singleton class which has a variable that was filled in the constructor. All other classes use data from the class at run time someone early someone later. Singleton class is created at the begin of main function. I am using singleton in different projects, data that it has mostly universal for all projects and modules except special flag which should show requirement for this module. If singleton throw exception program exits and we know it at the first steps of execution because singleton creates at first lines of the main. So singleton has a lot of universal data for all projects but I need to add flags to point for singleton which data is required for each module. I have created template for main so for each project I have the same main with just simple define PROJECT_NAME later I add .cpp to the project and they have to register which data is required and which not.
This explanation not looks like perfect, if it is not understandable don't hesitate to say it I will organize it more deliberately.
Edited:
I'm still looking for solution in the Internet, and found constexpr it looks like what I need, but at this moment it is not supported by all compilers, is there some workaround ?
First step is to not use global variables, but instead use static variables within a global function. The first time the function is called the variable will be initialized and then have the function return a reference to the varaible.
my_class& instnace() {
static my_class i;
return i;
}
A list example:
std::list<my_class>& global_list() {
static std::list<my_class> m; return m;
}
static int x = []()->int{ global_list().push_back(my_class); return 0;}();
If you want to accomplish what you want from different modules , one of the way is to have things done is some sort of callback function when your dll is loaded.
One windows it is DLLMain.
An optional entry point into a dynamic-link library (DLL). When the
system starts or terminates a process or thread, it calls the
entry-point function for each loaded DLL using the first thread of the
process. The system also calls the entry-point function for a DLL when
it is loaded or unloaded using the LoadLibrary and FreeLibrary
functions.
On other platforms with gcc you can get by the [attribute constructor]
constructor The constructor attribute causes the function to be called
automatically before execution enters main (). Similarly, the
destructor attribute causes the function to be called automatically
after main () has completed or exit () has been called. Functions with
these attributes are useful for initializing data that will be used
implicitly during the execution of the program. These attributes are
not currently implemented for Objective-C.
Warning
It is very easy to shoot yourself in the foot with this method. At least on windows that are lot of things you cannot do in the dll entry point. Please read your compiler/os documentation to see what the limitations are.

How to mimic the "multiple instances of global variables within the application" behaviour of a static library but using a DLL?

We have an application written in C/C++ which is broken into a single EXE and multiple DLLs. Each of these DLLs makes use of the same static library (utilities.lib).
Any global variable in the utility static library will actually have multiple instances at runtime within the application. There will be one copy of the global variable per module (ie DLL or EXE) that utilities.lib has been linked into.
(This is all known and good, but it's worth going over some background on how static libraries behave in the context of DLLs.)
Now my question.. We want to change utilities.lib so that it becomes a DLL. It is becoming very large and complex, and we wish to distribute it in DLL form instead of .lib form. The problem is that for this one application we wish to preserve the current behaviour that each application DLL has it's own copy of the global variables within the utilities library. How would you go about doing this? Actually we don't need this for all the global variables, only some; but it wouldn't matter if we got it for all.
Our thoughts:
There aren't many global variables within the library that we care about, we could wrap each of them with an accessor that does some funky trick of trying to figure out which DLL is calling it. Presumably we can walk up the call stack and fish out the HMODULE for each function until we find one that isn't utilities.dll. Then we could return a different version depending on the calling DLL.
We could mandate that callers set a particular global variable (maybe also thread local) prior to calling any function in utilities.dll. The utilities DLL could then use this global variable value to determine the calling context.
We could find some way of loading utilities.dll multiple times at runtime. Perhaps we'd need to make multiple renamed copies at build time, so that each application DLL can have it's own copy of the utilities DLL. This negates some of the advantages of using a DLL in the first place, but there are other applications for which this "static library" style behaviour isn't needed and which would still benefit from utilities.lib becoming utilities.dll.
You are probably best off simply having utilities.dll export additional functions to allocate and deallocate a structure that contains the variables, and then have each of your other worker DLLs call those functions at runtime when needed, such as in the DLL_ATTACH_PROCESS and DLL_DETACH_PROCESS stages of DllEntryPoint(). That way, each DLL gets its own local copy of the variables, and can pass the structure back to utilities.dll functions as an additional parameter.
The alternative is to simply declare the individual variables locally inside each worker DLL directly, and then pass them into utilities.dll as input/output parameters when needed.
Either way, do not have utilities.dll try to figure out context information on its own. It won't work very well.
If I were doing this, I'd factor out all stateful global variables - I would export a COM object or a simple C++ class that contains all the necessary state, and each DLL export would become a method on your class.
Answers to your specific questions:
You can't reliably do a stack trace like that - due to optimizations like tail call optimization or FPO you cannot determine who called you in all cases. You'll find that your program will work in debug, work mostly in release but crash occasionally.
I think you'll find this difficult to manage, and it also puts a demand that your library can't be reentrant with other modules in your process - for instance, if you support callbacks or events into other modules.
This is possible, but you've completely negated the point of using DLL's. Rather than renaming, you could copy into distinct directories and load via full path.