[SOLVED] Destruktoren wann werden sie aufgerufen und wann nicht?



  • Hallo,

    ich glaube ich habe wohl etwas noch nicht kapiert, nach all dieser Zeit. Kann mir jemand erklären, weshalb bei diesem Beispiel Programm der Wert nicht geloggt wird, wenn ich das fenster einfach schließe, bevor das Programm auf "natürlichem" Wege sich beendet. Ich hätte gedacht es werden trotzdem alle Destruktoren aufgerufen?

    #include <fstream>
    #include <string>
    #include <iostream>
    
    template<typename T>
    class WriteOnClose {
    public:
        WriteOnClose(const T& type, const std::string& filename)
            :m_type { type }, m_file { filename }
        {
        }
        ~WriteOnClose()
        {
            std::ofstream os(m_file);
            os << m_type;
        }
    private:
        const T& m_type;
        std::string m_file;
    };
    
    int main()
    {
        const std::string filename { "usage.txt" };
        unsigned long long bytes {};
        {
            std::ifstream file(filename);
            if (!file) {
                {
                    std::ofstream f(filename);
                }
                file.open(filename);
            }
            file >> bytes;
        }
        std::cout << "bytes: " << bytes << '\n';
        WriteOnClose<unsigned long long> byte_log(bytes, filename);
        bytes += 500;
        std::cout << "bytes: " << bytes << '\n';
        char ch;
        std::cin >> ch;
    }
    

    Wenn ich einen char für std::cin eingebe und das Programm beendet wird natürlich in die Datei geschrieben. Nur ich meinte das würde es auch auf dem anderen Weg.

    Dann meine nächste Frage, ich habe ein Programm das nach dem Anmelden automatisch startet, und eine praktisch Endlosschleife ausführt, bis es beim abmelden terminiert wird. Sollte ich dann am besten einfach in einem definierten Abschnitt (z.B. 30 Sekunden) einen "snapshot" in die Datei schreiben und weiter machen?

    P.S.: Es soll mit winpcap die Internetnutzung geloggt werden (dazu will ich alle packets capturen und die größe der Packets aufaddieren)



  • Schließt du das Konsolenfester, wird das Programm einfach abgeschossen, jedenfalls meiner Erfahrung nach. Demzufolge werden auch keine Destruktoren aufgerufen.



  • HarteWare schrieb:

    Hallo,
    Ich hätte gedacht es werden trotzdem alle Destruktoren aufgerufen?

    eig werden da auch die destruktoren aufgerufen, also auch wenn du "das fenster schließt".

    also bei mir klappt das:

    #include <iostream>
    #include <vector>
    #include <fstream>
    
    class TestKlasse
    {
    private:
    	int zahl;
    	std::string wort;
    	std::fstream testStreamOut;
    	std::string datei;
    
    public:
    
    	TestKlasse(int eingabeZ, std::string eingabeW, std::string datei)
    	{
    		zahl = eingabeZ;
    		wort = eingabeW;
    		testStreamOut.open(datei.c_str(), std::ios::out|std::ios::app);
    	}
    
    	~TestKlasse()
    	{
    		std::cout << "Zahl-Destruktor: " << zahl << "\n";
    		std::cout << "Wort-Destruktor: " << wort << std::endl;
    
    		testStreamOut << "Zahl-Destruktor: " << zahl << "\n"
    						<< "Wort-Destruktor: " << wort << "\n"
    									<< "---------------------- \n";
    
    		testStreamOut.close();
    	}
    };
    
    int main()
    {
    	std::string testString;
    	int testZahl;
    
    	std::cout << "Eingabe(testString): " << std::endl;
    	std::cin >> testString;
    
    	std::cout << "Eingabe(testZahl): " << std::endl;
    	std::cin >> testZahl;
    
    	TestKlasse tK1(testZahl,testString, "test.txt");
    
    	std::cout << "Jetzt das Fenster Schließen." << std::endl;
    	std::cin >> testString;
    }
    

    HarteWare schrieb:

    Dann meine nächste Frage, ich habe ein Programm das nach dem Anmelden automatisch startet, und eine praktisch Endlosschleife ausführt, bis es beim abmelden terminiert wird. Sollte ich dann am besten einfach in einem definierten Abschnitt (z.B. 30 Sekunden) einen "snapshot" in die Datei schreiben und weiter machen?

    P.S.: Es soll mit winpcap die Internetnutzung geloggt werden (dazu will ich alle packets capturen und die größe der Packets aufaddieren)

    was meinst du mit "am besten" - für was? 🙄
    wozu ein snapshot? 🙄

    ich weiß nicht genau ob ich dich richtig verstanden habe.
    aber wenn würde ich in vorher festgelegten zeitabschnitten (z.B. 30sek) die werte sammelen und dann schreiben.

    warum? - um möglichst keine daten zu nicht zu schreiben, sofern das möglich ist bzw. überhaupt gewünscht ?

    ansonsten was ist das problem?

    hoff ich konnte helfen
    lg



  • Witzig, bei mir ist die Datei noch leer am Ende 🙂 Ich verwende Win7 (buuh ich weiß).

    Ich werde mal es versuchen, in bestimmten Abständen zu schreiben, und nicht nur beim ProgrammEnde. Scheint auch irgendwie weniger "gehackt" zu sein, wenn man nicht Destruktoren zum Datei schreiben missbraucht^^#

    Vielen Dank an alle Helfended.

    LG



  • HarteWare schrieb:

    Witzig, bei mir ist die Datei noch leer am Ende 🙂 Ich verwende Win7 (buuh ich weiß).

    Ich werde mal es versuchen, in bestimmten Abständen zu schreiben, und nicht nur beim ProgrammEnde. Scheint auch irgendwie weniger "gehackt" zu sein, wenn man nicht Destruktoren zum Datei schreiben missbraucht^^#

    Vielen Dank an alle Helfended.

    LG

    ok, muss ich nochmal testen, ich habs unter debian-linux ausgeführt...
    komisch, eig sollte auch unter win7 der destruktor aufgerufen werden ...

    jo 👍 , obwohl das eig funktionieren sollte so das du verbleibende "werte" noch schreiben kannst...

    bist du dir sicher das du die richtige datei überprüfst?
    bist du sicher das nichts anderes diesen fehler bei dir verursacht?
    hast du den code von mir benutzt?

    der destruktor sollte bei ende des programms ausgeführt werden.

    lg



  • Destruktoren werden aufgerufen, wenn das Programm regulär beendet wird. Wenn auf Linux beim Schließen des Fensters nur stdin geschlossen wird, erhält das Programm einen Fehler beim Lesen und beendet sich regulär. Wird das Programm mit SIGKILL beendet, wird kein Destruktor aufgerufen.



  • Nach kurzer Recherche bin ich auf das hier gestoßen (für Windows, wo das Problem ja auftritt):

    Closing a c++ console app with the "x" in the top corner throws an CTRL_CLOSE_EVENT which you could catch and process if you set a control handler using the SetConsoleCtrlHandler function.

    SIGBREAK is raised on Windows.

    Dadurch würde sich sowas ergeben:

    #include <iostream>
    #include <fstream>
    #include <windows.h>
    
    BOOL WINAPI HandlerRoutine(DWORD ctrl_type)
    {
        if (ctrl_type != CTRL_CLOSE_EVENT) return false;
        std::ofstream os("f.txt");
        os << "blubb\n";
        return true;
    }
    
    int main()
    {
        SetConsoleCtrlHandler(&HandlerRoutine, TRUE);
        std::cout << "Jetzt das Fenster schliessen\n";
        char ch;
        std::cin >> ch;
    }
    

    Wie ich jetzt zusätzliche Parameter an den Callback übergeben kann, ist mir natürlich ein Rästel. Ist aber auch Stoff für einen anderen Thread. Ich hab jetzt eh die Methode eingebaut, wo in einem Zeitabschnitt geschrieben wird.

    LG


Anmelden zum Antworten