Question

A few days ago, my company changed our operation system from Windows XP to Windows 7 (32-bit) for security matters.

I use C++ in VS 2008, QT 4.8.1, and Boost. Struct Member Alignment in my application is 1 byte (/Zp1).

After the change, I found one bug:

I load the library I made with QPluginLoader and then I use qobject_cast to cast it to my interface. In my library I might load another.

When I test my application on Debug mode after the operating system changed, it was all OK. Everything was working like it suppose to, then I changed it to Release and my application started crashing.

When I debugged it with VS 2008, I saw this error:

A buffer overrun has occurred in my_app.exe which has corrupted the program's internal state. Press Break to debug the program or Continue to terminate the program.

For more details please see Help topic 'How to debug Buffer Overrun Issues'.

The application still work fine on Windows XP (Release and Debug mode).

At the beginning, I thought it was because of a dependency or something I missed. After a couple of hours testing and tracing my application with logging in Release mode, I finally found out what was wrong. My application crashes when one method tries to return a value (anything) to another that called it inside the library.

For example:

Method B return Bool and I call it in Method A. When Method B is finished and ready to return a Bool value to Method A, wy application crashes. It also crashes when it wants to return to the method that loaded the library, if the method returns a value. Somehow, it's ok with a method that don't return any value (void).

To be sure what is wrong exactly, the code inside my methods, I made another application (tester) and started to add my code part-by-part to find the error. I believe it has something to do with QT.

Please check the following code and tell me if you know what is wrong.

I have main.cpp that loads a plugin like this:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString filename = "correct path";

    QPluginLoader* pluginLoader = new QPluginLoader(filename);

    QObject *plugin = pluginLoader->instance();

    PluginInterface* plugin_instance;

    if (plugin) 
    {
        
        SecureZeroMemory(&plugin_instance, sizeof(PluginInterface));

        plugin_instance = qobject_cast<PluginInterface *>(plugin);

    }

    bool result = plugin_instance->initialize();

    return a.exec();
}

This is my interface:

class PluginInterface
{
public:

    virtual bool initialize() = 0;
};

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(PluginInterface,"some text");
QT_END_NAMESPACE

I make my library like this:

plugin.hpp

class Plugin : public QObject, public PluginInterface
{
    Q_OBJECT
    Q_INTERFACES(PluginInterface)

public:
    Plugin();
    bool initialize();  
};

plugin.cpp

#define SUPPORTED_VERSIONS  0x01011403
#define WFS_TRACE_NONE      0

bool Plugin::initialize()
{
    WFSVERSION wfs_version;
    HRESULT hRes;

    cout << "WFSStartUp" << endl;

    hRes = WFSStartUp(SUPPORTED_VERSIONS, &wfs_version);

    WORD version = wfs_version.wVersion;

    cout << "version : " << version << endl;

    DWORD dwTrace = WFS_TRACE_NONE;

    cout << "WFSCreateAppHandle" << endl;

    HRESULT hRes2;
    HANDLE app_handle;
    hRes2 = WFSCreateAppHandle(&app_handle);

    cout << "Result : " << hRes2 << endl;

    return true;
}
Q_EXPORT_PLUGIN2(my_plugin, Plugin);

This is the output of my tester application:

WFSStartUp
version : 63424
WFSCreateAppHandle
Result : 0
Application Crash!!

The code inside Plugin::initialize() works fine. I copy/paste it to main() and ran the application to be sure about it.

What is wrong here? What am I missing?

Was it helpful?

Solution 3

I had to change few Visual Studio build options to fix this problem!

  • Optimization = Custom (Configuration Properties -> C/C++ -> Optimization)
  • Inline Function Expansion = Default (Configuration Properties -> C/C++ -> Optimization)

OTHER TIPS

This code:

PluginInterface* plugin_instance;

if (plugin) 
{

    SecureZeroMemory(&plugin_instance, sizeof(PluginInterface));

    plugin_instance = qobject_cast<PluginInterface *>(plugin);

}

would be very much crash-inducing if SecureZeroMemory does what its name says it does.

To zero a pointer just set it to 0.

But, to mention also that, that would be meaningless when the next thing you do is to assign to it, as above.

I already tested without SecureZeroMemory and it still crash, SecureZeroMemery its not the cause of the crash!

Quite probably there are other bugs like that in other places in the code - places that you don't show.

At the very least, are you compiling everything in your application (all libraries, DLLs, etc.) with the same compiler, and using same settings? If you use "/Zp1", you must use it for every piece of code, including Qt itself. Such compiler flags make the code compiled with them binary incompatible with code compiled without them.

Besides, "/Zp1" is a performance killer. If you want to pack structures for dumping them to disk etc., you're going about it the wrong way. The structure that you use shouldn't be packed. Only when you're copying it to/from disk should you have another structure defined internally that is packed, and you first copy the data from unpacked to packed structure, and only then dump to disk. You're supposed to pack individual structures by using proper pragmas/attributes, not everything!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top