When C++ DLL Program Exits: Run-Time Check Failure #2 - c++

I am having trouble with a dll I am writing in C++. There is some very strange behavior going on that I have not been able to solve on my own.
It's hard to describe exactly what's going on, but I will try my best. Basically I have a class in my DLL with a single private property and a public constructor. When I initialize this class and then exit the program I get an error.
"Run-Time Check Failure #2 - Stack around the variable 'test' was
corrupted"
I have 2 projects here:
The DLL named "testdll".
The console test program named "test".
I have boiled this error down to its simplest reproducible form to try and narrow down the possible causes, below you will find my code.
Project "testdll", file testdll.h:
#include <string>
class testdll
{
public:
__declspec(dllexport) testdll(); // Empty but same error if prams are used.
private:
std::string _var;
};
Project "testdll", file testdll.cpp:
#include "testdll.h"
testdll::testdll()
{
}
Project "test", file testdll.h:
#include <string>
class testdll
{
public:
__declspec(dllimport) testdll();
};
Project "test", file stdafx.h:
#pragma once
#include "targetver.h"
#include <tchar.h>
Project "test", file test.cpp:
#include "stdafx.h"
#include "testdll.h"
int _tmain(int argc, _TCHAR* argv[])
{
testdll test;
return 0;
}
If you want I can send you the Visual C++ 2010 solution file, in the archive format of your choice. Please help! I have no idea what's going on.
Optional Information:
Language (or Software): C++
Already Tried:
Deleting the constructor definition, which works but is not a usable solution, nor does it explain the problem. Also making all of my private properties into pointers works, however I should not have to do this.

You are using two header files, they don't declare the same class. One has a std::string member, the other doesn't. That's very very bad, the compiler doesn't reserve enough space for the object on the stack frame. Which is what the runtime error is telling you. Very nice feature btw, this kind of mistake is incredibly hard to diagnose otherwise.
You probably got into this pickle because you only applied __declspec(dllexport) to the constructor instead of the entire class. You'll need to write the header file so it can be used by both your dll project and your exe project. That should look like this:
#undef DLLEXPORT
#ifdef BUILDING_MYDLL
# define DLLEXPORT __declspec(dllexport)
#else
# define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT testdll
{
public:
testdll();
private:
std::string _var;
};
Right-click your DLL project, Properties, C/C++, Preprocessor, Preprocessor Definitions. Append BUILDING_MYDLL
And delete the testdll.h file in your exe project directory. Set the C/C++, General, Additional Include Directories setting so the compiler can find the header in the testdll project directory (like ..\testdll)

Exporting classes and class members from a DLL is very VERY fragile, as you have just discovered. If the library and client don't both use the exact same class layout, which depends on all kinds of compiler settings, things fail horribly.
In your case, you're probably using incompatible versions of std::string inside class testdll. Maybe one is compiled for debug and one for release. Or one is using the static runtime library and the other the DLL runtime. Who can say?
Anyway, as soon as you export C++ features from a DLL, you lock yourself in to that compiler version and settings. It's a maintenance nightmare.
Use v-table-only base classes or C-compatible wrapper functions.

Related

Calling function from dll with QT

I created by the first time a dll to use with C++ (and then C#, I have plans to share this dll between a C++ and C# applications) using QT creator but when I try to use it I get SEGFAULT error.
Here's my files:
mydll.h
#ifndef MYDLL_H
#define MYDLL_H
#include "mydll_global.h"
class MYDLLSHARED_EXPORT MyDll
{
public:
MyDll();
int getAnswer();
};
MYDLLSHARED_EXPORT int getNumber();
#endif // MYDLL_H
mydll_global.h
#ifndef MYDLL_GLOBAL_H
#define MYDLL_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MYDLL_LIBRARY)
# define MYDLLSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYDLLSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYDLL_GLOBAL_H
mydll.cpp
#include "mydll.h"
MyDll::MyDll()
{
}
int MyDll::getAnswer()
{
return 42;
}
int getNumber()
{
return 10;
}
So I build it and created mydll.dll: then I went to other C++ project wheere I want to use this dll and put in the .pro file:
LIBS += "C:\path\to\mydll.h"
and in the main.cpp
#include "mydll.h"
and when I use function from dll like this:
qDebug() << getNumber();
I get a SEGFAULT error.
I thought that the header to provide the compiler type information and the dll to compiler to provide the function body was all I needed but as I'm getting a SEGFAULT I'm acessing NULL or someone else memory or so (I can't see the value on debug).
What am I missing?
First off, to link the DLL you need the link .lib file for that DLL. That file has all the binary manifest for linking.
Second, project file LIBS clause specify the list of .lib files to link with. Some of them may represent dynamic libraries (.dll).
See the example: Linking to Shared Library in Qt
Even better article covering both creation of DLL with Qt and using DLL in your Qt project: https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application
I had this same issue. Almost every example I looked at had a class as their example, but I wanted to export functions like getNumber(). It's in the qt5 docs as you probably know by now.
This line needs to be in your header file:
extern "C" MYDLLSHARED_EXPORT int getNumber();
and it is either the mydll_global.h or mydll.h depending on what you are using.
mydll_global.h would be what qtcreator creates and puts export definitions in if you create a new Shared Library project.
I was thrown off guard by the extern "C" part as I wasn't using C and wasn't as familiar with how compilers export symbols.
Trying to add a public static function to a class definition using static MYDLLSHARED_EXPORT int getNumber(); or simply using a namespace (function defined with or without static) will give a not found for architecture x86_64 error using clang on osx.

Using Lib file alonside DLL (as apposed to function pointers)

I've always found it a bit of a pain that you have to use LoadLibrary() and define function pointers when wanting to make use of a DLL, it just feels a bit archaic when so much is automated now days. So when I stumbled across a forum post explaining that the VS auto-generated lib file that always (in my experience) gets compiled alonside your DLL can be used to save yourself the hassle, as a sort of auto-import mechanism, I figured I'd put it to the test.
I created two very minimal projects to test this, but it doesn't appear to be working.
The code in its entrirety for the DLL:
extern "C"
{
__declspec(dllexport) int get10()
{
return 10;
}
}
And for the exe (an otherwise empty Win32 console app):
#include <Windows.h>
#pragma comment(lib, "Kernel32.lib")
#pragma comment(lib, "dll1.lib")
__declspec(dllimport) int get10();
int main(int, char**)
{
int x = 0;
if (LoadLibrary(L"dll1.dll") != NULL)
{
x = get10();
}
return 0;
}
dll1.dll and dll1.lib are local and visible to the project, but when I go to link it get10() is unresolved. If I remove the call to this it builds and runs and the LoadLibrary() call succeeds.
I also tried copying across the dll1.exp, just clutching at straws really, but that didn't help either.
Is what I'm trying to do actually valid?
By the way I appreciate you'd usually just use a lib file proper, it just grabbed my curiosity for circumstances where you might have these dll and "reduced" lib files but not have the source to compile a regular lib file.
You either link as static, or as dynamic.
So, in essence, you need __declspec(dllexport) only if you're loading the function at runtime by name. Read some of this, for example.
As mentioned here, regarding __declspec(dllexport):
This convenience is most apparent when trying to export decorated C++ function names. Because there is no standard specification for name decoration, the name of an exported function might change between compiler versions. If you use __declspec(dllexport), recompiling the DLL and dependent .exe files is necessary only to account for any naming convention changes.

how to share class between c++ projects?

My VS2012 Solution contains several VC++ projects.
I also have many common files that need to be shared.
It's easy to share enum's and structures. I just "include" corresponding header file and that's it. I even don't need to compile my "commons" project!
But what if I need to share more complex classes that contain both .h and .cpp files, and so need to be compiled?
And the most complicated question - can I share thread-safe singleton? I want to access it from different projects from different threads (but from one process).
I guess I should use something like static or dynamic linking, but i'm not sure. Probably someone can link step-by-step tutorial to solve such problem?
I would prefer something portable as I will move entire solution to Linux later.
The projects that contain classes that you want to share should export their symbols. When you create a DLL project in Visual Studio you can give it the option to "Export" symbols and it provides some boiler-plate code for you to use.
In essence, in your libraries header file, it will give you:
// myapi.h
#if defined(MYAPIEXPORTS)
#define MYAPI __declspec(dllexport)
#else
#define MYAPI __declspec(dllimport)
#endif
'MYAPIEXPORTS' is provided by the wizard, but it's a compiler preprocessor directive ONLY on the library itself. Hence when you compile the library, MYAPI is for exporting and when the header file is included in your other projects, it will be for importing.
Now let's look at a class you want to share.
// myclass.h
class MYAPI MyClass
{
public:
MyClass();
~MyClass();
};
// myclass.cpp
#include "myClass.h"
MyClass::MyClass() { /* ... */ };
MyClass::~MyClass() { /* .... */ }
Your other projects then need to link with the resulting .lib file that is generated.
Note that if you have a template<> class contained entirely within a header file, you do not export it. That will behave like your enums and typedefs.
To answer the second part of your question, yes a singleton defined in your library will be accessible to the main project also.

Pitfalls for breaking up a large file into one DLL?

I am not that experienced in creating DLL's in MSVC++ 2010, just may be a few times as part of the learning curve. At the moment I have a very large file with about 10 different classes in it. I have to breakdown the file into multiple files and move out related classes to the same file. So before proceeding wanted to know from experienced developers about my situation.
Something like the following
// Header
namespace collections
{
classA
classB
ClassC
ClassD : ClassA,ClassB
}
// CPP
namespace collections
{
classA
{
// Implementations
}
// Rest of the classes
}
After breaking down to separate files
// ClassA.h
namespace Collections
{
ClassA
}
// ClassB.h
namespace Collections
{
ClassB
}
// Implentations etc
My main concern is the usage of dllexport/dllimport storage class attributes
Since The file will be broken up I would have to use the following
#ifdef MAKEDLL
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __declspec(dllimport)
#endif
against the classes to export/import them. But placing these line in each header file that will be create (with one namespace "Collections"), will this have any bad implications while compiling or code generation step? I was looking around on-line and found out that people most complain about linker errors/warnings where a particular member is redefined or is not found whilst creating DLL's. This must definitely be a solved issue just that I dont know which is the best and proper way of doing it.
I need to create just one DLL in the end. I dont need to create multiple DLL's.
Any guidance or help is much appreciated.
Thank you
There is no issue to have one common header file that defines the EXPORTS macro:
mydll.h
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
And have this header file included in other header files:
ClassA.h
#include "mydll.h"
namespace Collections
{
class MYDLL_API ClassA {
// ...
}
}
ClassA.cpp
#include "ClassA.h"
// ...
ClassB.h
#include "mydll.h"
namespace Collections
{
class MYDLL_API ClassB {
// ...
}
}
... and so on. You can have all of them (header files and .cpp implementation files) in one DLL, having MYDLL_EXPORTS defined in your DLL project settings (it is automatically done by the VS2010 DLL wizard).
There is nothing weird here. You never redefine anything.
You just use the handy MYDLL_API to add a decorator to all your DLL API classes.

Compiler Warning C4251: Problem exporting a class in a *.dll

EDIT: Forgive my noobish-ness, I haven't ever implemented a wrapper .dll before! :S
I've been tinkering a bit with some of the recently released Kinect Sensor hacks (namely OpenKinect and OpenNI) and I'm now trying to wrap the functionality in a *.dll for use in various "test" programs that I hope to write.
So far I've set up a *.dll project and have got a lot of the library functionality in, however I'm getting C4251 compiler warnings all over the place.
In the project settings I've got the OpenNI.lib file statically linked, so far my library header looks like this:
#ifdef LIBKINECT_EXPORTS
#define LIBKINECT_API __declspec(dllexport)
#else
#define LIBKINECT_API __declspec(dllimport)
#endif
// This class is exported from the LibKinect.dll
class LIBKINECT_API CLibKinect
{
public:
CLibKinect(void);
~CLibKinect(void);
bool Init(void);
protected:
private:
xn::Context m_xContext;
xn::DepthGenerator m_xDepthGen;
};
And my stdafx.h file contains:
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <XnOpenNI.h>
#include <XnCodecIDs.h>
#include <XnCppWrapper.h>
Now I've attempted to create a windows console app to test the library and I get lots of error C2653: 'xn' : is not a class or namespace name errors. I was hoping that in the application I would only have to include and link to the wrapper *.dll not all of the OpenNI stuff as well, so as to hide the underlying implementation, is this incorrect?
Since you want to hide the fact you are using xn namespace in your implementation, you should not put that in the library header file. The simplest way to solve this problem is to use the pimpl idiom.