0

**** 업데이트 : 나는 리눅스에 괜찮아요 만 Windows에서 세그먼트 폴트를 얻을 것으로 나타났습니다. Windows에서는 QT 5.5와 MinGW32를 사용합니다. 나는 아직도 이유를 알고 싶다.는 QNetworkAccessManager-> 포스트()를 사용하여 응용 프로그램을 닫기에 SEGV가 발생

**** 초기 질문 : 여기 아무것도 까다로운, 나는 기본 콘솔 응용 프로그램을 만들 수 있습니다. QNetworkAccessManager가 Post() 요청을 보내도록했습니다. 콘솔을 닫을 때 segfault가 있습니다. 요청이 전송되고 성공적으로 수신

참고, 내 질문은 해당 세그먼트 폴트에 관한 것입니다. 더 포스트() 요청이 전송되지 않으면

콘솔을 닫는에 아무런 충돌. 스택에서 많은 도움이되지 않습니다.

스택

0 ntdll!RtlFreeHeap   0x77b5e041 
1 ucrtbase!free   0x5e4c5eab 
2 LIBEAY32!CRYPTO_free   0x5e5a123e 

하여 Main.cpp

#include <QCoreApplication> 
#include "CNetworkHandleTest.h" 

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

    CNetworkHandleTest net; 
    net.start(); 

    return a.exec(); 
} 

CNetworkHandleTest.cpp

#include "CNetworkHandleTest.h" 

CNetworkHandleTest::CNetworkHandleTest() 
{ 
    m_Manager = new QNetworkAccessManager(this); 
    // Connect the network manager so we can handle the reply 
    connect(m_Manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*))); 
    m_nTotalBytes = 0; 
} 

CNetworkHandleTest::~CNetworkHandleTest() 
{ 
    disconnect(); 
    m_Manager->deleteLater(); 
} 

void CNetworkHandleTest::onFinished(QNetworkReply* reply) 
{ 
    // Look at reply error 
    // Called when all the data is receivedqDebug() << "Error code:" << reply->error(); 
    qDebug() << "Error string:" << reply->errorString(); 
    reply->close(); 
    reply->deleteLater(); 
} 

void CNetworkHandleTest::start() 
{ 
    // Configure the URL string and then set the URL 
    QString sUrl(BASE_URL); 
    sUrl.append("/console/5555/upload"); 
    m_Url.setUrl(sUrl); 

    // Make the request object based on our URL 
    QNetworkRequest request(m_Url); 

    // Set request header (not sure how or why this works, but it works) 
    // \todo investigate 
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlenconded"); 

    // Make file object associated with our DB file 
    QFile file("/tx_database.db"); 
    if(!file.open(QIODevice::ReadOnly)) 
    { 
     qDebug() << "Failed to open file"; 
    } 

    // Read the entire file as a binary blob 
    QByteArray data(file.readAll()); 

    // Set our request to our request object 
    // Note: there should probably be a flag so that when start is called it does not do 
    // any processing in case we are already in the middle of processing a request 
    m_Request = request; 

    // Send it 
    m_Reply = m_Manager->post(m_Request, data); 

    // Need to connect the signals and slots to the new reply object (manager makes a new 
    // reply object every post; may need to investigate if memory should be freed when 
    // done processing a response) 
    connect(m_Reply, SIGNAL(readyRead()), this, SLOT(onReadyRead())); 
    connect(m_Manager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), 
      this,  SLOT(onAuthenticationRequired(QNetworkReply*, QAuthenticator*))); 
} 

void CNetworkHandleTest::onReadyRead() 
{ 
    // Whenever data becomes available, this slot is called. It is called every time data 
    // is available, not when all the data has been received. It is our responsibility to 
    // keep track of how much we have received if we want to show progress or whatever 
    // but we do not need to keep track if we have received all the data. The slot 
    // OnFinished will be called when the all the data has been received. 

    qDebug() << "Bytes available:" << m_Reply->bytesAvailable(); 
    m_nTotalBytes += m_Reply->bytesAvailable(); 
    qDebug() << "Bytes thus far:" << m_nTotalBytes; 
    QByteArray responseData = m_Reply->readAll(); 
    qDebug() << "Response" << responseData; 
    m_Reply->size(); 
} 

void CNetworkHandleTest::onAuthenticationRequired(QNetworkReply* reply, QAuthenticator* authenticator) 
{ 

} 

CNetworkHandleTest.h

#ifndef CNETWORKHANDLETEST_H 
#define CNETWORKHANDLETEST_H 

// Required packages 
#include <QNetworkAccessManager> 
#include <QNetworkRequest> 
#include <QNetworkReply> 
#include <QByteArray> 
#include <QUrlQuery> 
#include <QHostInfo> 
#include <QObject> 
#include <QUrl> 

// Helper packages 
#include <QCoreApplication> 
#include <QFile> 
#include <QDir> 

// Our packages 
#include <iostream> 
#include <fstream> 
#include <cstdlib> 

#define BASE_URL "localhost:5000" 
#define BOUNDARY "123456787654321" 

class CNetworkHandleTest : public QObject 
{ 
    Q_OBJECT 

public: 
    CNetworkHandleTest(); 
    ~CNetworkHandleTest(); 

    void start(); 

protected Q_SLOTS: 

    void onFinished(QNetworkReply* reply); 
    void onReadyRead(); 
    void onAuthenticationRequired(QNetworkReply* reply, QAuthenticator* authenticator); 

private: 

    QNetworkAccessManager* m_Manager; 
    QNetworkRequest  m_Request; 
    QNetworkReply*  m_Reply; 
    QUrl     m_Url; 

    int    m_nTotalBytes; 
}; 

#endif // CNETWORKHANDLETEST_H 
+0

'onFinished()'에서 신호를 내보내고이를 응용 프로그램의 'quit()'슬롯에 연결할 수 있습니다. 양도가 완료되면 신청서가 종료됩니다. 현재 내가는 Windows의 세그먼트 폴트를 얻을 것으로 나타났습니다 충돌 –

+0

결과 종단의 양식을 실행할 수있는 응용 프로그램을 종료, 리눅스에 괜찮아요. Windows에서는 QT 5.5와 MinGW32를 사용합니다. 나는 아직도 이유를 알고 싶다. – vincedjango

+1

터미널 코드가 닫혀있을 때 기본 코드가 신호를 처리하지 않거나 Windows가 프로그램을 종료하는 데 사용하고있는 것입니다. Linux에서는 표준 신호 일 가능성이 높고 응용 프로그램이 정상적으로 종료되도록하는 반면 Windows에서는 가능하지 않을 수 있습니다. m_manager' '의'deleteLater'이 불필요하다고 http://stackoverflow.com/questions/20511182/catch-windows-terminal-closing-on-running-process –

답변

1

콘솔을 닫으면 프로그램이 가장 비관적으로 종료됩니다. 대신이 우아하게 코드를 작성해야합니다 아래의 완전한 테스트 케이스 인 경우, CTRL-C를 누르거나 콘솔 창에 [x]을 클릭하면

// https://github.com/KubaO/stackoverflown/tree/master/questions/network-cleanup-40695076 
#include <QtNetwork> 
#include <windows.h> 

extern "C" BOOL WINAPI handler(DWORD) 
{ 
    qDebug() << "bye world"; 
    qApp->quit(); 
    return TRUE; 
} 

int main(int argc, char *argv[]) 
{ 
    SetConsoleCtrlHandler(&handler, TRUE); 
    QCoreApplication a(argc, argv); 

    QNetworkAccessManager mgr; 
    int totalBytes = 0; 

    QObject::connect(&mgr, &QNetworkAccessManager::finished, [](QNetworkReply *reply){ 
     qDebug() << "Error string:" << reply->errorString(); 
    }); 

    QNetworkRequest request(QUrl{"http://www.google.com"}); 
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlenconded"); 

    auto reply = mgr.post(request, QByteArray{"abcdefgh"}); 
    QObject::connect(reply, &QIODevice::readyRead, [&]{ 
     qDebug() << "Bytes available:" << reply->bytesAvailable(); 
     totalBytes += reply->bytesAvailable(); 
     qDebug() << "Bytes thus far:" << totalBytes; 
     reply->readAll(); 
    }); 
    QObject::connect(reply, &QObject::destroyed, []{ 
     qDebug() << "reply gone"; 
    }); 
    QObject::connect(&mgr, &QObject::destroyed, []{ 
     qDebug() << "manager gone"; 
    }); 
    return a.exec(); 
} 

, 종료가 질서이며, 출력이되는 :

[...] 
bye world 
reply gone 
manager gone 
관련 문제