Invalid address specified in RtlValidateHeap in multiple DLL application when using QTcpSocket

Background:
Sorry, this is such a difficult problem, but it turns me on. Finding a solution can help others who need a split application.

I have a Qt program that is VERY segmented because it is designed to host plugins and can be used in a variety of situations, sometimes as a server, sometimes as a client, sometimes as both. The plugins that are loaded depend on the input. (Because user-specific access is not necessarily user-specific, and the user can access data and functionality.)

The application relies on a core DLL (application specific) that is used by the core exe, client, server and all DLL plugins. The client and server functions are also in separate DLLs. I am new to this style of programming, so this might lead to my problem.

My problem:
I have a class called "BidirectionalTcpConnection" which is defined in the base DLL that should be used by the executable, client dll and server dll. This is the class that keeps track of the data sent back and forth over the QTcpSocket. I wrote a class to avoid the problem I am currently facing, except that the problem occurred when using the QTcpSocket.ReadAll () function AND in the current situation. (If I tried reading everything but the last byte and then reading the last byte using the QTcpSocket.peek (...) function, it works fine).

My new class successfully reads and writes to the socket without error, but when I try to close or interrupt the socket (this happened with my previous workaround ...) I get the same error I was getting when I tried to read it (only on last byte). I am getting an invalid address specified for RtlValidateHeap. It basically generates a User Breakpoint in the dbgheap.c file

My hypothesis (which I believe is wrong):
The dbgheap.c docs check if the address is valid and that it is in the current heap.

It is possible that the need to detach my application could lead to this issue. The data sent to the socket for sending was initially allocated on the executable heap along with the BidirectionalTcpConnection instance. (I am trying to submit a login and get permissions to access the application). However, the socket itself is allocated on the kernel heap (assuming the dll has a separate heap from the exe for internal data). I tried to avoid this by making a deep copy of every piece of data that needs to be sent over the socket in the core dll code. But that didn't solve the problem. Presumably because the BidirectionalTcpConnection is still allocated on a separate heap from the socket itself.

My question for those who can help:

  • Is the assumption correct in my hypothesis?
  • Do I need to assign socket and connection on the same heap? How can I overcome this problem?
  • Also ... if you look at the code, would I need to remove the returned string that the executable in the core dll needs to handle to avoid the same issue?

If you guys need some code ... I put in what I think is needed. I can provide more upon request.

Code:
For starters ... here is some basic code to show how things are distributed. Logging in is done mainly before the main interface is displayed. w is the main instance of the interface class. Here is the code that starts the crashing process:

while (loginFailed)
{
    splash->showLogin();
    while (splash->isWaitingOnLogin())
        a.processEvents();

    QString username(*splash->getUserName());
    QString password(*splash->getPassword());
    // LATER: encrypt login for sending
    loginFailed = w.loginFailed(username, password, a);
}

      

Here is the code that starts the BidirectionalTcpConnection on the executable stack and sends the login credentials. This code resides inside several separate private methods of the Qt main window class.

// method A
// processes Qstring parameters into sendable data...
// then calls method B 
// which creates the instance of *BidirectionalTcpConnection*
...
if (getServerAddress() == QString("LOCAL"))
    mTcpConnection = new BidirectionalTcpConnection(getHostAddressIn()->toString(),
        (quint16)ServerPorts::loginRequest, (long)15, this);
else
    mTcpConnection = new BidirectionalTcpConnection(*getServerAddress(), 
        (quint16)ServerPorts::loginRequest, (long)15, this);

...
// back to method A...
mTcpConnection->sendBinaryData(*dataStream);
mTcpConnection->flushMessages(); // sends the data across the socket
...

// waits for response and then parses user data when it comes
while (waitForResponse)
{
    if (mTcpConnection->hasBufferedMessages())
    {
        QString* loginXML = loginConnection->getNextMessageAsText(); 
        // parse the xml
        if (parseLogin(*loginXML))
        {
            waitForResponse = false;
        }
        ...
     }
}
...

// calls method that closes the socket which causes crash
mTcpConnection->abortConnection();  // crash occurs inside this method
delete mTcpConnection;
mTcpConnection = NULL;

      

Here is the corresponding BidirectionalTcpConnection code in order to use it. Note, this code is in the kernel, so it is assumed to allocate data on a separate stack ...

BidirectionalTcpConnection::BidirectionalTcpConnection(const QString& destination, 
    quint16 port, long timeOutInterval, TimeUnit unit, QObject* parent) : 
    QObject(parent),
    mSocket(parent),
    ...
    { }

void BidirectionalTcpConnection::sendBinaryData(QByteArray& data)
{ 
    // notice I try and avoid different heaps where I can by copying the data...
    mOutgoingMessageQueue.enqueue(new QByteArray(data)); // member is of QQueue type
}

QString* BidirectionalTcpConnection::getNextMessageAsText()
// NOTE: somehow I need to delete the returned pointer to prevent memory leak
{
    if (mIncomingMessageQueue.size() == 0)
        return NULL;
    else
    {
        QByteArray* data = mIncomingMessageQueue.dequeue();
        QString* stringData = new QString(*data);
        delete data;
        return stringData;
    }
}

void BidirectionalTcpConnection::abortConnection()
{
    mSocket.abort();  // **THIS CAUSES ERROR/CRASH**
    clearQueues();
    mIsConnected = false;
}

      

+3


source to share





All Articles