Instantiation of QAxObject from dumpcpp segfault with minGw C++ -o2 or -o3 flag

119 Views Asked by At

Qt version: 5.12.10

I wanted to interface with an application using the COM layer, this application was delivered with a .tlb file so I used Qt's dumpcpp to generate header and source file.

To use the generated class, I first get an IUnknown from windows ROT and then instantiate the classes I need from a class I used an interface.

My code looks like this :

Code instantiating my class:

 //Initialize COM, load the ROT, get the monikers and for each monikers

 //Check if the monikers name is the one we want
 if (!wcsncmp(monikerDisplayName, appComIdentifier, wcslen(appComIdentifier)))
 {
     qDebug() << "Found app";

     IUnknown *currentObject = nullptr;
     if (rot->GetObject(currentMoniker, &currentObject) == S_OK)
     {
         AppCommunication appCom(static_cast<app::IApplicationInterface *>(new QAxObject(currentObject)));
     }
 }

The AppCommunication class:

Header file:


class AppCommunication : public IAppCommunication
{
public:
    AppCommunication(app::IApplicationInterface *applicationInterface);

    ~AppCommunication() override = default;

private:
    app::appApplication appApplication;
    app::appJob appJob;
};

cpp file:

AppCommunication::AppCommunication(app::IApplicationInterface *applicationInterface)
    : appApplication(applicationInterface),
      appJob(static_cast<app::IJobInterface *>(new QAxObject(appApplication.CreateJobObject())))
//     ^
//     |
//    Segfault here

{

}

All the classes under the app namespace are the ones generated by the dumpcpp tool.

This works perfectly fine with the optimization flags -o0 or -o1 in the compiler but when I set -o2 or -o3 my program crashes.

From what I could trace this is the instantiation of the appJob (not the fetching of the JobInterface) that causes the crash.

I consider Qt's code and Qt's generated code to be robust/validated enough so I think this error must be me having an undefined behaviour. But I can not see what I did wrong here.

EDIT: I managed to find a way to avoid the issue. What I have found is that if I use a pointer instead of the class by itself it works fine:

Header file:

class AppCommunication : public IAppCommunication
{
public:
    AppCommunication(app::IApplicationInterface *applicationInterface);

    ~AppCommunication() override = default;

private:
    app::appApplication appApplication;
    app::appJob *appJob;
};

cpp file:

AppCommunication::AppCommunication(app::IApplicationInterface *applicationInterface)
    : appApplication(applicationInterface),
      appJob(new app::appJob(static_cast<app::IJobInterface *>(new QAxObject(appApplication.CreateJobObject()))))
{

}

And this also work with a unique_ptr instead of the raw pointer so this is the route I will take.

I am more and more starting to think this is a MinGW because I can't see what could cause an issue like that...

1

There are 1 best solutions below

0
On BEST ANSWER

The mistake was on me.

After getting the IUnknown * from the COM, we have to get a IDispatch * from it and then instantiate directly the classes:

 //Initialize COM, load the ROT, get the monikers and for each monikers

 //Check if the monikers name is the one we want
 if (!wcsncmp(monikerDisplayName, appComIdentifier, wcslen(appComIdentifier)))
 {
     qDebug() << "Found app";

     IUnknown *currentObject = nullptr;
     if (rot->GetObject(currentMoniker, &currentObject) == S_OK)
     {
         //Add the get dispatch part
         IDispatch *currentObjectDispatch = nullptr;
         HRESULT hr = currentObject->QueryInterface(IID_IDispatch, (void **)&currentObjectDispatch);
         if (FAILED(hr))
         {
             return;
         }
         //Get the interface directly without static cast
         AppCommunication appCom(new app::IApplicationInterface(currentObjectDispatch));
        // Use the class instance with some method calls
     }
 }

And do the same on the class we retrieve in the ctor:

AppCommunication::AppCommunication(app::IApplicationInterface *applicationInterface)
    : appApplication(applicationInterface),
      appJob(new app::IJobInterface(appApplication.CreateJobObject()))
{

}