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



  • wofür der frei stehende

    QMutexLocker locker(&m_MtxProcess);
    

    in Zeile 84? Was soll der machen?



  • Ah, dein Erzeuger Prozess wartet auf das Wakeup aus dem erstellten Thread?? Ungewöhnlich und habe ich noch nicht so gesehen. Normalerweise wartet ein Thread darauf, dass er vom Ersteller oder einen anderen Thread abgeholt wird.

    Wie rufst du die Funkionen deines VisaAgilent denn auf?
    Du musst da doch irgendwie sowas haben:

    main(){
    VisaAgilent = agilent(...); // ruft Konstruktor auf und erstellt ersten Thread. Wartet bis der Fertig ist
    agilent.open(); //Open connection-> erstellt auch einen Thread. Wartet auch bis der fertig ist.
    } // Destruktor -> erstellt auch einen Thread, wartet wieder bis der fertig ist.
    

    So hast du nie einen wirklich nebenläufigen Programmablauf (oder habe ich was total übersehen???)

    Deine unterschiede zwischen Debug und Release wird in deinem Fall wahrscheinlich darauf zurückzuführen sein, dass Destruktoren schon mal weg optimiert werden dürfen.



  • Gast3 schrieb:

    wofür der frei stehende

    QMutexLocker locker(&m_MtxProcess);
    

    in Zeile 84? Was soll der machen?

    Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.



  • Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.

    wofür das lock wenn du nichts veränderst?

    oder ist der Code den du zeigst unvollständig?



  • Schlangenmensch schrieb:

    Ah, dein Erzeuger Prozess wartet auf das Wakeup aus dem erstellten Thread?? Ungewöhnlich und habe ich noch nicht so gesehen. Normalerweise wartet ein Thread darauf, dass er vom Ersteller oder einen anderen Thread abgeholt wird.

    Wie rufst du die Funkionen deines VisaAgilent denn auf?
    Du musst da doch irgendwie sowas haben:

    main(){
    VisaAgilent = agilent(...);
    

    // ruft Konstruktor auf und erstellt ersten Thread. Wartet bis der Fertig ist

    agilent.open();}
    

    //Open connection-> erstellt auch einen Thread. Wartet auch bis der fertig ist.
    // Destruktor -> erstellt auch einen Thread, wartet wieder bis der fertig ist.

    Fast
    anbei einen Codeabschnit:

    VisaAgilent DSO_l(.....);/* Object referenzieren*/
    DSO_l.open(); //Bis hier ist alles gut
    // wenn es z.b open verlassen wird also Object "DSO_l" verlassen, wird dann das Destructor aufgerufen und da kracht warum ? --> weiss ich nicht
    

    Schlangenmensch schrieb:

    So hast du nie einen wirklich nebenläufigen Programmablauf (oder habe ich was total übersehen???)

    Deine unterschiede zwischen Debug und Release wird in deinem Fall wahrscheinlich darauf zurückzuführen sein, dass Destruktoren schon mal weg optimiert werden dürfen.



  • Gast3 schrieb:

    Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.

    wofür das lock wenn du nichts veränderst?

    oder ist der Code den du zeigst unvollständig?

    Sorry ich verstee nicht welchen lock meinst du ?



  • Ich sehe grade, dass open auch schon aus dem Konstruktor aufgerufen wird.

    Aber du wirst deinen Code vollständiger posten müssen, aber bitte auf das reduziert, was nötig ist um den Fehler zu reproduzieren.

    Der Destruktor von DSO_l wird aufgerufen, wenn du den Scope verlässt in dem du das erstellt hast. Wobei ich, wie gesagt, davon ausgehe, dass der im Release Modus möglicherweise gar nicht aufgerufen wird.



  • Sorry ich verstee nicht welchen lock meinst du ?

    in deinen Beispiele hier im Forum, Zeile 84



  • Gast3 schrieb:

    Sorry ich verstee nicht welchen lock meinst du ?

    in deinen Beispiele hier im Forum, Zeile 84

    das habe ich doch geantwortet warum:
    Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.



  • Schlangenmensch schrieb:

    Ich sehe grade, dass open auch schon aus dem Konstruktor aufgerufen wird.

    Aber du wirst deinen Code vollständiger posten müssen, aber bitte auf das reduziert, was nötig ist um den Fehler zu reproduzieren.

    Der Destruktor von DSO_l wird aufgerufen, wenn du den Scope verlässt in dem du das erstellt hast. Wobei ich, wie gesagt, davon ausgehe, dass der im Release Modus möglicherweise gar nicht aufgerufen wird.

    Ist das Object VisaAgilent DSO_l(....) aufgerufen wird, wird dann der Konstrukt VisaAgilent(QString strIpAdress_p, int iTimeout_p, bool boSimulate_p, bool boDebug_p) aufgerufen.

    Der Konstrukt ist so implementiert:

    VisaAgilent::VisaAgilent(QString strIpAdress_p, int iTimeout_p, bool boSimulate_p, bool boDebug_p)
    {	
    	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("Constructor TcpSocket Create memory error"));
    	}
    
    	this->Open(strIpAdress_p, iTimeout_p);
    }
    

    also folgende verlauf ist vorgesehen:

    1. Objeckt erzeugen:
      diese geschieht wie folgende Implementierung zeigt:
    VisaAgilent::t_enRspType VisaAgilent::Execute(const char *strCmd_p, const int iWaitResponse_p, const int iTimeout_p, const int iRspDelayed_p)
    {
    	VisaAgilent::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();
    
    		enRetVal_l = this->m_enRetVal;
    	}
    	else
    	{
    		enRetVal_l = enRspError;
    	}
    
    	while(isRunning());
    
    	return enRetVal_l;
    }
    

    In diesen Methode wird run() "Thread" gestartet, die so aussieht:

    void VisaAgilent::run()
    {
    	bool boRun_l = true;
    	bool boSent_l = false;
    
    	const char *pStrCmd_l = NULL;
    	const char *pStrRsp_l = NULL;
    
    	m_enRetVal = enRspError;
    
    	if (strcmp(m_ByteArrayWrite.data(),"CreateObject")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl = (QTcpSocket *)new QTcpSocket;
    			if (m_pTcpSctCtrl != NULL)
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    
    		boRun_l = false;
    	}
    
    	if (strcmp(m_ByteArrayWrite.data(),"DeleteObject")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    		}
    		else
    		{
    			if (m_pTcpSctCtrl != NULL)
    			{
    				delete m_pTcpSctCtrl;
    			}
    		}
    
    		m_enRetVal = enRspOK;
    		boRun_l = false;
    	}
    
    	if (strcmp(m_ByteArrayWrite.data(),"OpenConnection")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl->connectToHost(m_strCtrlIP,5025);
    			if (m_pTcpSctCtrl->waitForConnected(m_iTimeout) == true)
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    
    		boRun_l = false;
    	}
    
    	if (strcmp(m_ByteArrayWrite.data(),"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;
    	}
    
    	int iTimeout_l = m_iTimeout;
    
    	while (boRun_l && (!this->m_boSimulate))
    	{
     		if (boSent_l == false)
    		{
    			boSent_l = true;
    			// Kommando absetzen
    			m_pTcpSctCtrl->write(m_ByteArrayWrite.data(),m_ByteArrayWrite.size());
    			// Auf Antwort warten
    			if (m_iWaitResponse >= 0)
    			{
    				QThread::msleep(m_iWaitResponse);
    			}
    			else
    			{
    				boRun_l = false;
    			}
    		}
    
    		// Anwort auf Kommando abwarten	
    		if ((m_pTcpSctCtrl->bytesAvailable() > 0) && (boRun_l == true))
    		{
    			m_MtxResponse.lock();
    
    			m_ByteArrayRead.append(m_pTcpSctCtrl->readAll());
    
    			if (m_boDebug)
    			{
    				throw(QString(m_ByteArrayRead.data()));
    			}
    
    			m_MtxResponse.unlock();
    
    			iTimeout_l = m_iTimeout;
    //			iTimeout_l = m_iWaitResponse;
    		}
    		else
    		{
    			if (m_pTcpSctCtrl->waitForReadyRead(iTimeout_l) == false)
    			{
    				m_MtxResponse.lock();
    
    				if (m_ByteArrayRead.size() == 0)
    				{
    					if (m_boDebug)
    					{
    						throw(QString("VisaAgilent Timeout"));
    					}
    					m_enRetVal = enRspTimeout;
    				}
    				else
    				{
    					m_enRetVal = enRspOK;
    				}
    
    				m_MtxResponse.unlock();
    
    				boRun_l = false;					
    			}
    		}
    	}
    
    	QThread::msleep(m_iResponseDelayed);
    
    	QMutexLocker locker(&m_MtxProcess);
    
    	m_WaitCondProcess.wakeOne();
    
    }
    
    1. Verbindung open, die wie folgende geschieht:
    bool VisaAgilent::Open(const QString &strCtrlIP_p, const int iTimeout_p)
    {
    	bool boRet_l = true;
    
    	m_strCtrlIP = strCtrlIP_p;
    
    	if (this->Execute("OpenConnection", 0, iTimeout_p, 0) != enRspOK)
    	{
    		throw(QString("Open TcpSocket Open Connection error"));
    	}
    
    	if (m_boDebug)
    	{
    		throw(QString("Tcp Socket is open"));
    	}
    
    }
    

    die wiederum der Thread aufrufen: seh bitte "run()"

    Wird von dieses Objekt VisaAgilent einen reference erzeugt, so ist immer dieses verlauf vorzugehen.
    Wird dann dieses Object verlassen, muss dann wieder aufgeraumt werden, was eigentlich der Destruktor macht.
    Destruktor Implementierung:

    VisaAgilent::~VisaAgilent()
    {
    	while(isRunning());
    
    	this->Close(m_iTimeoutClose);
    
    	while(isRunning());
    
    	if (this->Execute("DeleteObject", 0, 0, 0) != enRspOK)
    	{
    		throw(QString("Destructor TcpSocket Delete memory error"));
    	}
    
    	while(isRunning());
    }
    

    Das Destruktor ruft wieder der "run()" von Thread um das Object zu löschen
    Ich hoffe es ist jetzt einigemassen klar was das gemacht wird.



  • das habe ich doch geantwortet warum:
    Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.

    und wofür ist das lock da wenn du nichts veränderst - einfach mal so oder aus einem Grund? der Code da braucht kein lock



  • Gast3 schrieb:

    und wofür ist das lock da wenn du nichts veränderst - einfach mal so oder aus einem Grund? der Code da braucht kein lock

    Genau habe ich ehrlich gesagt nicht nachgedacht, aber du hast recht.
    Lock brauche ich in diesem Code nicht
    Danke für den Hinweis



  • [quote="Gast3"]

    unter Windows könntest du die Trial-Version vom Intel-Inspector (https://software.intel.com/en-us/intel-inspector-xe) drauflassen

    Ich habe das installiert aber was es gezeigt wird entspricht nicht das Problem, was ich habe.

    Es wird auf andere Qt Library gezeigt, was es wirklich nicht unbedingt das Problem entspricht.

    Ich glaube es ist eine Synchronisation problem.



  • Apropos Synchronisation... Was passiert denn wenn

    m_WaitCondProcess.wakeOne();
    

    aufgerufen wird bevor

    m_WaitCondProcess.wait(&m_MtxProcess,-1);
    

    aufgerufen wurde.



  • Schlangenmensch schrieb:

    Apropos Synchronisation... Was passiert denn wenn

    m_WaitCondProcess.wakeOne();
    

    aufgerufen wird bevor

    m_WaitCondProcess.wait(&m_MtxProcess,-1);
    

    aufgerufen wurde.

    Tread wird nie beendet also SW bleibt hängen



  • Warum nimmst du nichst das normale wait(). Dann kannst du dir das wakeOne() sparen.



  • Schlangenmensch schrieb:

    Warum nimmst du nichst das normale wait(). Dann kannst du dir das wakeOne() sparen.

    Wenn ich das so implementiere dann bleibt die Application auch hängend.
    Also Thread wird ne beendet.



  • Wenn du wait() in deine Execute hinzufügst

    VisaAgilent::t_enRspType VisaAgilent::Execute(const char *strCmd_p, const int iWaitResponse_p, const int iTimeout_p, const int iRspDelayed_p)
    {
        VisaAgilent::t_enRspType enRetVal_l = enRspOffline;
    
        if (!isRunning()) // kann es passieren, dass du Execute aufrust und der Thread schon läuft? Du startest den doch hier erst und willst dann auf die Beendigung warten
        {
            m_ByteArrayRead.clear();
    
            m_ByteArrayWrite.clear();
            m_ByteArrayWrite.append(strCmd_p);
    
            m_iWaitResponse = iWaitResponse_p;
            m_iTimeout = iTimeout_p;
            m_iResponseDelayed = iRspDelayed_p;
    
            start();
    
            this->wait(); 
            //oder 
            if(!this->isFinished())
               this->wait();           
    
            enRetVal_l = this->m_enRetVal;
        }
        else
        {
            enRetVal_l = enRspError;
        }
    
        while(isRunning());  //Da du nach dem Thread start() auf die Beendigung wartest, solltest du das auch nicht brauchen.
    
        return enRetVal_l;
    }
    

    und in run()

    QThread::msleep(m_iResponseDelayed);
    
        QMutexLocker locker(&m_MtxProcess);
    
        m_WaitCondProcess.wakeOne();
    

    entfernst, beendet sich deine Software nicht?

    Edit: Was ich eigentlich schreiben wollte, wenn du dein Source Code so postest, dass ich den per Copy&Paste ans laufen bringen kann, probiere ich das heute abend mal aus.

    Edit2: Insbesondere habe ich keine Lust mir die ganzen Includes raus zu suchen.



  • Schlangenmensch schrieb:

    .... beendet sich deine Software nicht?

    Es tritt die gleiche Fehlermeldung



  • @ Schlangenmensch

    Es gibt so viele Abhängigkeiten, was das Copy&Paste schwierige machen.
    Dazu wir eine Hardware gebraucht sonst geht es nicht.


Anmelden zum Antworten