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



  • 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.



  • @Schlangenmensch

    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
    

    eigentlich nicht, da ich bei jeden Zugriff (refernce von Obj) auf das Objekt "VisaAgilent" immer darauf achte dass der Thread beendet wird.
    Diese ist zu sehen in:

    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;
    }
    

    Also

    VisaAgilent::t_enRspType VisaAgilent::Execute(.....)
    

    ist eine zentrale Methode.
    Jeden Thread Aufruf wird über diese Methode geschehen

    @Schlangenmensch

    while(isRunning());  //Da du nach dem Thread start() auf die Beendigung wartest, solltest du das auch nicht brauchen.
    

    Wie kritisch, wenn ich das so lasse?



  • Kritisch sollte das isRunning() nicht sein. Aber dient halt nicht der Übersichtlichkeit. Code der nicht gebraucht wird, kann gestrichen werden.

    Und wenn es darum geht Fehler zu finden, ist es manchmal eine gute Idee den Code auf das Nötigste zu reduzieren.

    Was passiert denn, wenn du nicht start() aufrufst, sondern direkt run(). Dann hast du keinen extra Thread, sondern einen einfachen sequentiellen Programmablauf (entsprechende Threadbedingte Codezeilen auskommentieren). Damit kannst du zumindest schon mal feststellen, ob dein Fehler tatsächlich im Multithreading Teil liegt.



  • Schlangenmensch schrieb:

    Kritisch sollte das isRunning() nicht sein. Aber dient halt nicht der Übersichtlichkeit. Code der nicht gebraucht wird, kann gestrichen werden.

    Und wenn es darum geht Fehler zu finden, ist es manchmal eine gute Idee den Code auf das Nötigste zu reduzieren.

    Was passiert denn, wenn du nicht start() aufrufst, sondern direkt run(). Dann hast du keinen extra Thread, sondern einen einfachen sequentiellen Programmablauf (entsprechende Threadbedingte Codezeilen auskommentieren). Damit kannst du zumindest schon mal feststellen, ob dein Fehler tatsächlich im Multithreading Teil liegt.

    SW bleibt hängend, wenn ich :

    //start();
    this->run();
    


  • Dann kannst du erstmal ganz klassich debuggen.

    Was gibt dir denn die Aufrufliste in VS aus? Interessant sind vor allem die letzten Aufrufe aus deinem Code?



  • Ich versuche hier wann und wie der oben genannten Fehler auftritt:
    ....
    Im laufe das Programm mache ich folgende:

    If(eine bestimmte Bedingung)
    {
    	VisaAgilent reference(......);
    	reference.ExecuteRUNControl(); // Task wird erfolgreich geschlossen
    }
    

    // wenn diesen Block "{}" verlassen wird, dann wird der Destruktor gerufen und der so ausieht:

    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());
    }
    

    diese wiederum ruft der close Methode, die so aussieht:

    bool VisaAgilent::Close(const int iTimeout_p)
    {
        bool boRet_l = true;
    
        while(isRunning());
    
        if (this->Execute("CloseConnection", 500, iTimeout_p, 1000) != enRspOK)
        {
            throw(QString("Close Connection error"));
        }
    
        if (m_boDebug)
        {
            throw(QString("Tcp Socket is closed"));
        }
    
        while(isRunning());
    
        return boRet_l;
    }
    

    dies ruft wieder

    Execute(...)
    

    Methode und genau in diesem Methode
    nach der

    start()
    

    Aufruf kracht die SW, da die

    run()
    

    Methode nicht aufgerufen wird was normaleweise nicht der Fall ist.
    Also

    run()
    

    muss immer automatische nach dem Aufruf von

    start()
    

    folgen.



  • Was ich grade sehe, du wirfst Exceptions im Destruktor und du hast auf VS 2015 umgestellt. VS 2015 kompiliert nach C++11 Standard.
    Danach ist jeder Destruktor impliziet noexcept. Wenn du doch Exceptions aus deinem Destruktor werfen willst musst du den Destruktor mit noexcept(false) deklarieren. Also in der Klassendeklaration:

    ~VisaAgilent() noexcept(false);
    

    Edit: Freitag Nachmittag hab ich's offensichtlich nicht mehr so mit dem Tippen.


Anmelden zum Antworten