kostenloser Webspace werbefrei: lima-city


Suche auf lima-city

  • in: gcc-gdb-Problem (C++): Ungewollte Optimierung?

    geschrieben von presencia

    Hallo darkpanedmic,

    ich bin noch nicht so weit, den Assembler-Code zu verstehen. Danke trotzdem für dein engagiertes Erklären desselben.

    Nach der Lektüre des ticpp-e-books habe ich mich auch entschlossen, meine Objekte nicht mehr by-value zu übergeben. Super: Ich habe deutlich dazu lernen können. Und somit kann ich dann auch wieder die neueren gcc-Versionen verwenden.

    Wahrscheinlich sollte ich trotzdem einen Bug-Report erstellen, damit der gcc ein bisschen besser werden kann. Ich habe auf http://gcc.gnu.org/bugzilla/ schon nach einem Report gesucht, der mein Problem beschreibt, habe einen solchen jedoch nicht gefunden. Ich finde die Suchfunktionen schwer zu bedienen und die Bug-Reports schwer verständlich.

    Danke nochmal für die schnellen Antworten. Ich sollte öfter hier posten, wenn ich Fragen habe.

    Gruß
    ~<><~~~~~~~ presencia

  • in: gcc-gdb-Problem (C++): Ungewollte Optimierung?

    geschrieben von presencia

    Hallo darkpandemic,

    danke für die superschnelle Antwort. Ich habe inzwischen den Abschnitt gelesen, und ein bisschen drum herum. Nettes online-Buch, danke für den Tipp. Allerdings geht es dort nur um das Problem, große Objekte zurückzugeben und nicht an die Funktion zu übergeben. Jedoch wenn du sagst, dass die Kopie im Stack-Bereich der aufrufenden Funktion ist, glaube ich es gern.

    Mein Problem mit dem gcc bleibt jedoch im Grunde bestehen. Selbst wenn es sich nicht um ungewollte Optimierung handelt, sind die Debugging-Informationen, die der gdb liest, nicht korrekt. Und das ist imho ein Fehler des Compilers und nicht des Debuggers. Entweder der Debugger sollte wissen, dass es sich bei i um eine Referenz und nicht um das Objekt selbst handelt, oder er sollte gleich an die referenzierte Adresse verwiesen werden, da findet man ja auch das korrekte I-Objekt.

    Ich habe mir heute mal die gcc-Versionen 4.5 und 4.1 installiert (bisher hatte ich nur 4.4). Wenn ich das Programm mit Version 4.5 kompiliere, ändert das nichts an dem Problem. Version 4.1 jedoch ändert scheinbar die Debugging-Informationen: Der Debugger erkennt nun i (in Zeile 13) als eine Referenz auf ein I-Objekt und gibt nun auch die korrekten Infos über i.p aus. Warum hat man das wohl geändert? Sind jetzt also die neueren gcc-Versionen fehlerhaft? (Leider konnte ich Version 4.6 bei mir nicht installieren).

    Gruß
    ~<><~~~~~ presencia
  • in: gcc-gdb-Problem (C++): Ungewollte Optimierung?

    geschrieben von presencia

    Hallo allerseits,

    ich habe hier ein etwas spezielles Problem beim Debuggen mit dem gdb. Eigentlich nutze ich Eclipse-CDT als Frontend, jedoch liegt das Problem offensichtlich an dem gcc-Compiler oder am gdb selbst. Daher habe ich es einmal ganz ohne Eclipse nachvollzogen.

    Mein Beispielprogramm
    Um das Problem einzugrenzen und zu erklären, habe ich folgendes "Minimalprogramm" geschrieben und als Datei "main.cpp" abgespeichert.
    #include<vector>
    #include <iostream>
    
    struct I{
    	std::vector<unsigned> p;
    	I() : p(std::vector<unsigned>(1,0)){
    		std::cout << "p has length " << p.size() << " and its first value is " << p[0] << std::endl;
    	}
    };
    
    struct T{
    	T (I i){
    		std::cout << "i.p has length " << i.p.size() << " and its first value is " << i.p[0] << std::endl;
    	}
    };
    
    int main(){
    	I i;
    	T t(i);
    }


    Dieses Programm habe ich wie folgt kompiliert (ich benutze Ubuntu 10.04, gcc-Version 4.4.3):
    g++ -O0 -g -o test main.cpp

    Es tut genau das Erwartete, wenn man es laufen lässt. Die Ausgabe ist

    p has length 1 and its first value is 0
    i.p has length 1 and its first value is 0


    Seltsames Verhalten beim Debugging
    Mein Problem ist das Debugging. Es geht um die Frage, ob der Konstruktor T::T(I) in Zeile 12 sein Argument i als Wert (call-by-value) oder als Referenz (call-by-reference) übergeben bekommt. Ersteres sollte imho der Fall sein. Auf der Kommandozeile ergibt sich folgende Debugging-Session (gestartet durch Eingabe von "gdb test"):

    GNU gdb (GDB) 7.1-ubuntu
    Copyright (C) 2010 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i486-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /home/jonathan/eclipse-workspace/test/test...done.
    (gdb) break main.cpp:19
    Breakpoint 1 at 0x80488ab: file main.cpp, line 19.
    (gdb) break main.cpp:13
    Breakpoint 2 at 0x8048a82: file main.cpp, line 13.
    (gdb) run
    Starting program: /home/jonathan/eclipse-workspace/test/test 
    p has length 1 and its first value is 0
    
    Breakpoint 1, main () at main.cpp:19
    19	T t(i);
    (gdb) print i
    $1 = {p = {<std::_Vector_base<unsigned int, std::allocator<unsigned int> >> = {
          _M_impl = {<std::allocator<unsigned int>> = {<__gnu_cxx::new_allocator<unsigned int>> = {<No data fields>}, <No data fields>}, _M_start = 0x804c008, _M_finish = 0x804c00c, 
            _M_end_of_storage = 0x804c00c}}, <No data fields>}}
    (gdb) print {unsigned int}0x804c008
    $2 = 0
    (gdb) c
    Continuing.
    
    Breakpoint 2, T (this=0xbffff41f, i=...) at main.cpp:13
    13			std::cout << "i.p has length " << i.p.size() << " and its first value is " << i.p[0] << std::endl;
    (gdb) print i
    $3 = {p = {<std::_Vector_base<unsigned int, std::allocator<unsigned int> >> = {
          _M_impl = {<std::allocator<unsigned int>> = {<__gnu_cxx::new_allocator<unsigned int>> = {<No data fields>}, <No data fields>}, _M_start = 0xbffff404, _M_finish = 0xbffff408, 
            _M_end_of_storage = 0x80486d4}}, <No data fields>}}
    (gdb) print {unsigned int}0xbffff404
    $4 = 134529048
    (gdb) print {I}0xbffff404
    $5 = {p = {<std::_Vector_base<unsigned int, std::allocator<unsigned int> >> = {
          _M_impl = {<std::allocator<unsigned int>> = {<__gnu_cxx::new_allocator<unsigned int>> = {<No data fields>}, <No data fields>}, _M_start = 0x804c018, _M_finish = 0x804c01c, 
            _M_end_of_storage = 0x804c01c}}, <No data fields>}}
    (gdb) print {unsigned int}0x804c018
    $6 = 0
    (gdb) c
    Continuing.
    i.p has length 1 and its first value is 0
    
    Program exited normally.
    (gdb) quit


    Ich erkläre die Schritte beim Debugging:
    Zunächst erstelle ich zwei Breakpoints, nämlich in Zeile 18 und 13. Dann starte ich das Programm im gdb, es wird bis vor Zeile 19 ausgeführt. Nun lasse ich mir das in Zeile 18 erstellte i ausgeben (also den Wert der Variablen i). Variable i ist vom Typ struct I und enthält daher nur ein std::vector<unsigned int>-Objekt. Dieses speichert die drei Pointer _M_start, _M_finish und _M_end_of_storage. Will ich auf den Wert des ersten Eintrags des Vektors zugreifen, so muss ich nur den Pointer _M_start dereferenzieren. Ich lasse mir also den Speicher an Stelle 0x804c008, geparsed als unsigned int ausgeben. Der Wert ist - wie erwartet und völlig zu Recht - 0. Nun lasse ich das Programm bis zum nächsten Breakpoint in Zeile 13 weiter laufen. Dort lasse ich mir wieder die Variable i ausgeben und dereferenziere den _M_start-Pointer. Der Wert ist 134529048, also nicht 0, wie er eigentlich sein sollte. Nun derefenziere ich den angeblichen _M_start-Pointer mal als Pointer auf ein Objekt der Klasse I, und siehe da, ich finde ein Ordentliches I-Objekt vor. Der Vektor i.p hat Länge 1 und sein erster Eintrag ist 0, wie man sieht. Ich lasse das Programm weiter laufen, es gibt mir seinerseits Informationen über i (über std::cout). Dann ist das Programm beendet und ich verlasse den gdb.

    Mein Fazit:
    Es scheint ganz so, als werde dem Konstruktor T::T(I) in Zeile 12 sein Argument i nicht als Wert übergeben, also als Kopie des Wertes i aus Zeile 18, wie man eigentlich vermuten sollte. Vielmehr scheint das i aus Zeile 18 zwar kopiert zu werden, aber dann wird dem Konstruktor nur eine Referenz (technisch: ein Pointer) auf diese Kopie übergeben. Streng genommen ist das weder call-by-value noch call-by-reference. Doch damit scheint der Konstruktor umzugehen können, wie die Ausgabe des Programms zeigt. Einzig der Debugger hält sich ganz an den Code (call-by-value) und interpretiert die Referenz nun als Wert der Variablen i, was zu Verwirrungen führt. Denn ich sehe beim Debuggen ein anderes i (print i) als mein Programm.

    Mein Problem damit:
    Ein solches Verhalten deutet eigentlich auf eine Art ungewollte Optimierung durch den Compiler hin. Doch ich habe ausdrücklich alle Optimierung verboten (Option -O0 beim Kompilieren). Ist das ein Compiler-Bug? Oder habe ich vielleicht etwas nicht richtig verstanden? Eigentlich ist es mir egal, wie die Übergabe der Parameter an meine Funktionen erfolgen, so lange sie tatsächlich kopiert werden (was ja auch hier geklappt hat) und mein Programm das tut, was es soll (auch das ist hier der Fall). Jedoch sind die Funktionen und Klassen bei meinen Programmier-Projekten deutlich komplizierter, und leider begegnet mir dieser Fehler an vielen Stellen beim Debuggen. Das erschwert mir die Arbeit sehr und macht eine Beobachtung der Werte meiner Variablen manchmal sogar unmöglich. Ich wüsste also auch gern, ob ich etwas dagegen tun kann.

    Sollte also irgend jemand eine Idee haben, woran es liegt oder was hier zu tun wäre, schreibt mir bitte.
    Gruß
    ~<><~~~~~~ presencia
  • in: Home Server

    geschrieben von presencia

    Hallo Spitzei,

    ich habe mit Ubuntu Server gute Erfahrungen gemacht. Das basiert auf Debian, jedoch ist die Software auf einem etwas neueren Stand als Debian stable, was natürlich auch heißt, dass die Testphase nicht ganz so lang war. Mit "neuerem Stand" meine ich auch nur die Features, nicht jedoch die Sicherheitsupdates.

    Was mich bei Ubuntu überzeugt, ist die Verbindung von Profi-Software (Debian) mit - wie ich finde - hervorragender Hilfe auch für Einsteiger. Die Community ist riesig, gerade auch im deutschsprachigen Raum, es sind gute Dokumentationen und gut besuchte Foren vorhanden, in denen auch ich schon oft Hilfe gefunden habe. Ich empfehle besonders ubuntuusers.de.

    Ich selbst habe mir auch einen kleinen Webserver aufgesetzt, einfach so zum Basteln und Probieren, und zum Testen von Webseiten. Außerdem nutze ich ihn als Backup-Server für meinen Arbeitsrechner. Ich hatte vorher schon ein wenig User-Erfahrung mit Ubuntu, was bei der Entscheidung gewiss auch eine Rolle spielte. Ich bin jedenfalls zufrieden damit, wie es läuft.

    ~<><~~~~~~~ presencia
  • in: C++ strcpy() Fehler

    geschrieben von presencia

    Hallo siteplayer,

    nun, das mit dem Compiler kommt wahrscheinlich darauf an, welches System du verwendest. Ich selbst hab ne Linux-Kiste und komme mit dem gcc gut klar, der ist weit verbreitet (viele Leute können bei Fragen also weiterhelfen), kostet nichts, wird aktiv entwickelt, ist zu ziemlich DER Standard für Linux. Wenn du den gcc (oder einen anderen Compiler) nicht immer wieder über lange Kommandos aufrufen willst, empfehle ich eine IDE, die mit dem Compiler kommuniziert. Dann kann man einfach z.B. per Mausklick den Build-Vorgang starten. Ich selbst verwende Eclipse mit CDT (www.eclipse.org/cdt/).

    Den gcc gibt es auch für Windows (Stichwort: MinGW), ist aber nach meiner (in Sachen Windows sehr kleinen) Erfahrung nicht so weit verbreitet, gängiger ist da Visual Studio (Ich glaube, die Express-Version ist kostenlos). Jedoch hat der gcc für mich den Charme, dass es wirklich freie Software ist und ihmo auch wirklich up to date.

    Hoffe, ich konnte dir weiterhelfen. (Das war mein erster Post in dieser coolen Community :-) )
    ~<><~~~~~ presencia

Login zum Webhosting ohne Werbung!