Application.exe has triggered a breakpoint Visual Studio 2015 C++



  • Schlangenmensch schrieb:

    Und was macht ExecuteRUNControl()? Die Funktion kam in den Code Ausschnitten, die du bisher gepostet hast nicht vor. Raten macht keinen Spaß!

    Du hast recht Sorry:

    void VisaAgilent::ExecuteRunControl(void)
    {
    	this->Execute("Run \n",200,1000,0);
    }
    

    Schlangenmensch schrieb:

    Was hast du denn von den Anmerkungen bisher umgesetzt?

    alle vorgeschlagene Erweiterungen habe ich umgesetzt.

    1. Entfernung der Exception aus der Destruktor
    m_pTcpSctCtrl = (QTcpSocket *)new QTcpSocket;
    

    zu

    m_pTcpSctCtrl = new QTcpSocket(this);
    

    umgeschrieben.

    Schlangenmensch schrieb:

    Hast du die Exception aus dem Destruktor entfernt?
    Selbst wenn dein Programm wo anders abstürtzt ist das so falsch!

    ja

    Könnte es sein, dass bei der Qt5.7 bzw. QTcpSocket einen Bug hat?

    Wie gesagt: ich habe dieses Projekt auch unter Visual studio 2008 mit Qt 4.8 Plug-In und dort laufen beide Versionen Debug/Release einwandfrei



  • Ich halte es für unwahrscheinlich, das Qt ein Bug hat, kann es aber nicht ausschließen.

    Bei dem Aufruf von welcher Codezeile genau stürtzt dein Programm ab?

    Was für ein Wert hat "m_boDebug"?

    Dann noch ein paar kleine Anmerkungen:

    Du übergibst deinem TCP Socket einen This Pointer. Der Pointer zeigt auf ein Objekt das von QThread erbt. QThread erbt von QObject, daher solltest du das nicht manuell löschen müssen.

    QTCPSocket::write kannst du direkt ein QByteArray übergeben. .data() ist nicht nötig (). Wenn sollte auch constData() verwendet werden.

    readAll(): hat keine Möglichkeit Fehler zu reporten. Eventuell wäre es besser eine normale "read()" Funktion zu benutzen, die die Anzahl an gelesenen Bytes zurück gibt und -1 bei Fehlern.



  • Schlangenmensch schrieb:

    Ich halte es für unwahrscheinlich, das Qt ein Bug hat, kann es aber nicht ausschließen.

    Bei dem Aufruf von welcher Codezeile genau stürtzt dein Programm ab?

    genau bei diese Zeile

    start();
    

    in diese FKT:

    VisaAgilent::t_enRspType VisaAgilent::Execute(const char *strCmd_p, const int iWaitResponse_p, const int iTimeout_p, const int iRspDelayed_p)
    {
        CAgilentLan::t_enRspType enRetVal_l = enRspOffline;
    
        if (!isRunning())
        {
            m_ByteArrayRead.clear();
    
            m_ByteArrayWrite.clear();
            m_ByteArrayWrite.append(strCmd_p);
    
            m_iWaitResponse = iWaitResponse_p;
            m_iTimeout = iTimeout_p;
            m_iResponseDelayed = iRspDelayed_p;
    
            start();
    
            m_MtxProcess.lock();
            m_WaitCondProcess.wait(&m_MtxProcess,-1);
            m_MtxProcess.unlock();// Prozess wird immer freigegeben
    
            enRetVal_l = this->m_enRetVal;
        }
        else
        {
            enRetVal_l = enRspError;
        }
    
        while(isRunning());
    
        return enRetVal_l;
    }
    

    Was für ein Wert hat "m_boDebug"?

    false
    

    Es ist als defaultValue bei der Konstructor:

    Header File:

    CAgilentLan(QString strIpAdress_p, int iTimeout_p, bool boSimulate_p = false, bool boDebug_p = false);
    

    Schlangenmensch schrieb:

    Dann noch ein paar kleine Anmerkungen:

    Du übergibst deinem TCP Socket einen This Pointer. Der Pointer zeigt auf ein Objekt das von QThread erbt. QThread erbt von QObject, daher solltest du das nicht manuell löschen müssen.

    Ist das eine Frage?

    Schlangenmensch schrieb:

    QTCPSocket::write kannst du direkt ein QByteArray übergeben. .data() ist nicht nötig (). Wenn sollte auch constData() verwendet werden.

    danke für den Hinweis schon geschehen

    Schlangenmensch schrieb:

    readAll(): hat keine Möglichkeit Fehler zu reporten. Eventuell wäre es besser eine normale "read()" Funktion zu benutzen, die die Anzahl an gelesenen Bytes zurück gibt und -1 bei Fehlern.

    Beim read brauche ich eine übergabe Parameter

    QByteArray read(qint64 maxlen);
    

    --> und die habe ich nit



  • Ich habe eher an: qint64 QIODevice::read(char *data, qint64 maxSize) gedacht.

    Überleg dir was für maxSize passt und lese so lange, bis keine Daten mehr im Stream sind. Also read "0" zurück gibt.

    Wenn du befürchtest, dass der Fehler im TCP Bereich liegt, würde ich nochmal den Multithreading part, raus nehmen. (nicht start() aufrufen, sondern direkt die run()). Und dann schauen wo, er in der run() rausfliegt. Dann kannst du auch mit dem Debugger durch steppen.

    Eine andere Möglichkeit wäre, die TCP Sachen mal auszukommentieren und testen ob es dann läuft (auch wenn nichts produktives passiert). Dann solange wieder einkommentieren, bis der Fehler lokalisiert ist.

    Saheb schrieb:

    Ist das eine Frage?

    Ja, das war eine Frage. Ich bin mir bei der Speicherverwaltung in QT nicht 100% sicher. Aber sonst knallst du mit einem double delete raus, das merkst du dann schon, wenn es nicht geht.

    Edit: readAll ist wahrscheinlich einfacher. Da kannst halt nur nicht zwischen "keine Daten da" und "Fehler" unterscheiden.



  • Schlangenmensch schrieb:

    Du übergibst deinem TCP Socket einen This Pointer. Der Pointer zeigt auf ein Objekt das von QThread erbt. QThread erbt von QObject, daher solltest du das nicht manuell löschen müssen.

    Vielen dank für den Hinweis.

    Schlangenmensch schrieb:

    .
    Wenn du befürchtest, dass der Fehler im TCP Bereich liegt, würde ich nochmal den Multithreading part, raus nehmen. (nicht start() aufrufen, sondern direkt die run()). Und dann schauen wo, er in der run() rausfliegt. Dann kannst du auch mit dem Debugger durch steppen.

    Wenn ich die statt start() run() nehme , dann bleibt die SW hängen

    Schlangenmensch schrieb:

    Eine andere Möglichkeit wäre, die TCP Sachen mal auszukommentieren und testen ob es dann läuft (auch wenn nichts produktives passiert). Dann solange wieder einkommentieren, bis der Fehler lokalisiert ist.

    Das habe ich gemacht.
    Wenn ich keine TCP Sachen benutze, dann lauft die SW einwandfrei.



  • Bei welchem TCP related Funktionsaufruf bleibt er denn hängen?



  • Schlangenmensch schrieb:

    Bei welchem TCP related Funktionsaufruf bleibt er denn hängen?

    Beim Object Erzeugung
    Object wird erzeugt und der Thread wird nicht mehr freigegeben.



  • Oh. Guter Hinweis und ich habe da eine blöde Vermutung.

    Du erstellst einen Thread. In dem Thread erzeugst du ein TCP Objekt auf dem Heap. Dessen Parent ist der Thread. Beim Beenden des Threads wird evt auch das TCP Objekt aufgeräumt.
    Um solche Unklarheiten zu vermeiden hatte ich vor vielen Posts schon mal geschrieben, dass ich eine extra Klasse nur für den Thread geschrieben und dann aus deinem VisaAgilent ein Thread Objekt erzeugt und mit thread.start() gestartet hätte.
    So ist mir tatsächlich grade nicht ganz klar, was passiert wenn der Thread beendet wird und wo drauf genau der this Pointer im Thread zeigt.

    Erstell das TCP Objekt mal außerhalb deines Threads, einfach um sicher zu gehen, was die Lebenszeit anbegeht.

    Wenn du hier schreibst, dass der Thread nicht mehr freigegeben wird, meinst du das der Fehler aus deinem ersten Post auftritt? Oder passiert inzwischen was anderes?

    //Edit: 2 Formulierungen angepasst.



  • Schlangenmensch schrieb:

    Oh. Guter Hinweis und ich habe da eine blöde Vermutung.

    Du erstellst einen Thread.
    In dem Thread erzeugst du ein TCP Objekt auf dem Heap.
    Dessen Parent ist der Thread.

    --> Ja

    VisaAgilent::VisaAgilent(QString strIpAdress_p, int iTimeout_p, bool boSimulate_p, bool boDebug_p):m_SDDevPeriodeA(0), m_SDDevDCA(0),m_SDDevDCB(0),m_SDDevWidthZ(0)
    {
    
    	m_boDebug = boDebug_p;
    	m_boSimulate = boSimulate_p;
    
    	m_enRetVal = enRspOffline;
    	m_strCtrlIP = QString("");
    	m_iTimeout = 0;
    	m_iTimeoutClose = iTimeout_p;
    	if (this->Execute("CreateObject", 0, 0, 0) != enRspOK)
    	{
    		throw(QString("Error VisaAgilent.CPP/Constructor TcpSocket Create memory error"));
    	}
    
    	this->Open(strIpAdress_p, iTimeout_p);
    }
    

    Execute sieht so aus:

    Execute(....)
    {
    	....
    	start();
    	...
    }
    

    die run() sieht so aus:

    run()
    {
    ...
    	if (strcmp(m_ByteArrayWrite.constData(),"CreateObject")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl = new QTcpSocket(this); 
    			if (m_pTcpSctCtrl != NULL)
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    
    		boRun_l = false;
    	}
    	......
    }
    

    Schlangenmensch schrieb:

    Beim Beenden des Threads wird also auch das TCP Objekt aufgeräumt.

    Ja

    run()
    {
    	....
    	if (strcmp(m_ByteArrayWrite.constData(),"DeleteObject")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    		}
    		else
    		{
    			if (m_pTcpSctCtrl != NULL)
    			{
    				delete m_pTcpSctCtrl; // muss ich hier delete ???? 
    			}
    		}
    
    		m_enRetVal = enRspOK;
    		boRun_l = false;
    	}
    }
    
    ..
    

    Schlangenmensch schrieb:

    Um solche Unklarheiten zu vermeiden hatte ich vor vielen Posts schon mal geschrieben, dass ich eine extra Klasse nur für den Thread geschrieben und du
    dann aus deinem VisaAgilent ein Thread Objekt erzeugt und mit thread.start() gestartet hätte.

    --> Warum soll ich besser eine extra Klasse für Thread schreiben?
    --> was für einen Sinn macht das?

    Schlangenmensch schrieb:

    So ist mir tatsächlich grade nicht ganz klar, was passiert wenn der Thread beendet wird.

    --> Es muss wieder freigegeben werden

    run()
    {
    ...
    if (strcmp(m_ByteArrayWrite.constData(),"CloseConnection")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl->disconnectFromHost();
    			if ((m_pTcpSctCtrl->state() == QAbstractSocket::UnconnectedState) || (m_pTcpSctCtrl->waitForDisconnected(m_iTimeout)))
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    
    		boRun_l = false;
    	}
    ....
    }
    

    Schlangenmensch schrieb:

    und wo drauf genau der this Pointer im Thread zeigt:

    --> lauf Qt Definition

    explicit QTcpSocket(QObject *parent = Q_NULLPTR);
    

    --> also QObject

    Schlangenmensch schrieb:

    Erstell das TCP Objekt mal außerhalb deines Threads, einfach um sicher zu gehen, was die Lebenszeit anbegeht.

    --> Das tue ich in so z.B ausserhalt der Thread:

    if(Bedingung)
    {
    	VisaAgilent DSO_l(......); // Object von typ VisaAgilent wird erzeugt
    	DSO_l.ExecuteRunControl();
    
    }
    

    Schlangenmensch schrieb:

    Wenn du hier schreibst, dass der Thread nicht mehr freigegeben wird, meinst du das der Fehler aus deinem ersten Post auftritt?

    nein.
    Es tritt keinen Fehler sondern der Thread wird nicht mehr freigegeben.
    Normalerweise es läuft so :
    Object erzeugen, dann task ausführen und beim Thread verlassen wieder freigeben.
    Wenn ich aber einen Object von Typ VisaAgilent verlasse, dann was auf dem Heap ist muss gelöscht werden.In diesem Fall m_pTcpSctCtrl

    Schlangenmensch schrieb:

    Oder passiert inzwischen was anderes?

    Nein



  • Ich glaube wir reden hier ziemlich aneinander vorbei und du hast nicht verstanden was ich meinte oder du hast Multithreading nicht richtig verstanden

    Ich versuche hier mal zu skizzieren was in deinem Programm passiert:

    Main Thread-------------thread1-----------------------------thread2
    ---|
    -Konstruktor-------------|
    -VisaAgilent-----------erstellt TCP objekt
    ---|-------------------wird beendet (was passiert
    ---|-------------------mit dem TCP Objekt
    --wartet auf
    --Thread

    ---
    -ExecuteRunControl----------------------------------------------
    -erzeugt wieder---------------------------------------------------

    -einen Tread-------------------------------------------------macht irgendwas
    ---|---------------------------------------------------------mit TCP Objekt
    ---|---------------------------------------------------------(wenn es denn noch lebt?)
    ---|--------------------------------------------------------Thread wird beendet
    -wartet auf thread

    ---

    -Destruktor
    -erzeugt wieder einen
    -Thread (den beschreibe
    -ich jetzt nicht)

    Saheb schrieb:

    --> Warum soll ich besser eine extra Klasse für Thread schreiben?
    --> was für einen Sinn macht das?

    Bessere Kapselung, klareres Verständnis was in deinem Code passiert, die Möglichkeit wirklich nebenläufig zu programmieren.

    Grobe Skizze wie ein Nebenläufiges Programm dann aussehen kann:

    • Erstelle Socket und öffne Verbindung
    • Erstelle n Threads die auf Socket schreiben/lesen (achtung gemeinsame Ressource)
    • Alle Threads haben ihre Arbeit erledigt
    • Schließe Socket
    • Programm fertig

    Edit: Mit TCP Objekt beziehe ich mich auf:

    m_pTcpSctCtrl = new QTcpSocket(this);
    

    und das findet bei dir doch im Code statt, der von start() aufgerufen wird.


Anmelden zum Antworten