Verweigerte Ausgabe



  • Hat denn keiner eine Idee, was der Fehler sein sollte? Von mir aus könnte ich auch den ganzen Code posten, aber ich glaube nicht, dass das etwas helfen würde.


  • Mod

    2und40 schrieb:

    Hat denn keiner eine Idee, was der Fehler sein sollte? Von mir aus könnte ich auch den ganzen Code posten, aber ich glaube nicht, dass das etwas helfen würde.

    niemand hier benutzt die glaskugel für so was. die argumentation ist auch fehlerhaft: da du die ursache nicht kennst, kannst du nicht wissen ob der nicht gepostete code nicht doch die ursache ist - und wenn wir schon davon ausgehen, das es kein compilerbug ist, dann muss sich das problem ja irgendwo dort finden lassen. das minimum wäre doch der code aller funktionen, die in diesem beispiel instantiiert werden. was probleme mit unbekannten bezeichnern betrifft: in dem code, den du gezeigt hast, hast du eben nicht <fstream> eingebunden - und da ostream kein abhängiger bezeichner ist, muss er bereits bei der deklaration bekannt. außerdem befindet sich ostream im namespace std...
    aber wie gesagt: ohne den minimalen code zum compilieren ist sowieso alles nur rätselraten.



  • Hast natürlich Recht mit std.

    Hier der Code:

    template<class T>
    Container<T>::Container(us l) : length(l)
    {
    	speicher = new T[l];
    
    	for(us = a; a < l; a++)
    	{
    		speicher[a] = T();
    	}
    }
    
    template<class T>
    Container<T>::Container(const T& quelle)
    {
    	(*this) = quelle;			// Zuweisungsoperator vorausgesetzt!
    }
    
    template<class T>
    us Container<T>::push_back(const T& quelle)
    {
    	T* buffer = new T[length];
    
    	for(us a = 0; a < length; a++)
    		buffer[a] = speicher[a];
    
    	delete[] speicher;
    
    	speicher = new T[length + 1];
    
    	for(a = 0; a < length; a++)
    		speicher[a] = buffer[a];
    
    	speicher[a] = quelle;
    
    	++length;
    	delete[] buffer;
    
    	return length;
    }
    
    template<class T>
    us Container<T>::push_front(const T& quelle = T())
    {
    	T* buffer = new T[length];
    
    	for(us a = 0; a < length; a++)
    		buffer[a] = speicher[a];
    
    	delete[] speicher;
    
    	speicher = new T[length + 1];
    
    	*speicher = quelle;
    
    	for(a = 1; a < length + 1; a++)
    		speicher[a] = buffer[a];
    
    	++length;
    	delete[] buffer;
    
    	return length;
    }
    
    template<class T>
    bool Container<T>::remove(us d)
    {
    T* buffer = new T[length];
    
    	for(us a = 0; a < length; a++)
    		buffer[a] = speicher[a];
    
    	delete[] speicher;
    
    	speicher = new T[length - 1];
    
    	for(a = 0; a < d; a++)
    		speicher[a] = buffer[a];
    
    	a++;
    
    	for(; a < length; a++)
    		speicher[a] = buffer[a];
    
    	--length;
    	delete[] buffer;
    
    	return true;
    }
    
    template<class T>
    us Container<T>::count(void) const
    {
    	return length;
    }
    
    template<class T>
    const T& Container<T>::operator [](us a) const
    {
    	if(a < length && a >= 0)
    		return speicher[a];
    
    	return speicher[a];
    }
    
    template<class T>
    void Container<T>::set(const T& quelle, us a)
    {
    	speicher[a] = quelle;
    }
    
    template<class T>
    Container<T>& Container<T>::operator =(const Container<T>& quelle)
    {
    	for(us a = 0; a < length; a++)
    		speicher[a] = quelle[a];
    
    	return (*this);
    }
    
    template<class T>
    void Container<T>::save(ofstream& file)
    {
    	for(us a = 0; a < length; a++)
    		file << speicher[a];
    }
    

  • Mod

    template<class T>
    Container<T>::Container(const T& quelle)
    {
          (*this) = quelle;            // Zuweisungsoperator vorausgesetzt!
    }
    

    nett - gemeint ist siche Container<T>::Container(const Container&) 😉
    so jedenfalls ist das eine endlosrekursion - worüber dich ein guter compiler auch informiert. im übrigen ist die implementation von copy-konstruktion durch copy-zuweisung semantisch fehlerhaft und extrem unschön. für gewöhnlich läßt das auf fehlendes verständnis für beide operationen schließen.



  • Was Copy-Konstruktor & Co machen sollen, ist mir schon klar.
    Danke für den Hinweis, ich wollte hier die Elemente von einem Container nach *this mit dem Zuweisungsoperator kopieren (oder ist das auch irgendwie unsauber?); keine Ahnung, warum ich das so geschrieben habe.
    Werds gleich mal ausbessern.



  • g++ 😃


  • Mod

    2und40 schrieb:

    Was Copy-Konstruktor & Co machen sollen, ist mir schon klar.
    Danke für den Hinweis, ich wollte hier die Elemente von einem Container nach *this mit dem Zuweisungsoperator kopieren (oder ist das auch irgendwie unsauber?); keine Ahnung, warum ich das so geschrieben habe.
    Werds gleich mal ausbessern.

    copy-zuweisung setzt ein fertig konstruiertes objekt voraus. prinzipiell muss also der vorherige zustand des objekts zerstört werden, bevor das objekt neu initialisiert wird - andernfalls gibt es ein resourcenleck. und hier ist das problem - damit der operator im konstruktor aufrufen werden kann, muss dieser konstruktor zumindest eine minimalinitialisierung durchführen - andernfalls zerstört der operator basierend auf nichtinitialisierten speicher, was undefiniertes verahlten ist. und das ist, wenn schon nichts anderes, extrem ineffizient. eine implementierung der zuweisung mittels copy-ctor ist ohne weiters möglich (z.b. per copy&swap) - der umgekehrte weg ist sehr fragwürdig und nie vorteilhaft.
    P.S. dein zuweisungsop funktioniert im übrigen auch nicht wenn das argument einen andere größe hat.



  • Und noch ein Hinweis: Für die ganzen insert- und remove-Funktionen machst du dir unnötig Arbeit. Da reicht es aus, wenn du die Daten einmal kopierst:

    us push_back(const T& val)
    {
      T* buffer = new T[length+1];
      for(int i=0;i<length;++i)
        buffer[i]=speicher[i];
      buffer[length]=val;
      delete[]speicher;
      speicher=buffer;
      return ++length;
    }
    

    (und von der Performance ist es noch besser, wenn du von vornherein mehr Platz reservierst als du im Moment benötigst (nimm dir ein Beispiel an vector<>)



  • Vielen Dank an alle, die mir geholfen haben, inzwischen läuft es.
    Keine Ahnung, wieso es so ist, aber anscheinend war der fehlerhafte Copy-Konstruktor die Fehlerquelle, nachdem ich den umgeschrieben habe, hat die Ausgabe funktioniert.
    Wenn mir jetzt noch jemand einen Tipp geben könnte, wie der Copy-Konstruktor mit der Ausgabe zusammenhängt, wäre ich vollkommen glücklich... 😕


  • Mod

    das war kein copy-konstruktor. und da sich dieser konstruktor rekursiv aufrief, ist dein program mit einem stack overflow ausgestiegen - der programmfluß hat den ausgabe ausdruck nie erreicht..
    ausführlich:
    der konstruktor nahm eine referenz auf konstantes T - für deine instanz also int. damit passt dieser konstruktor besser auf das argument in main() als derjenige, der ein unsigned short nimmt. der andere konstruktor wird also nie aufgerufen (andernfalls hätte sich dein compiler auch über den syntaxfehler darin beschwert).



  • Was auch der Grund ist, warum man beim Debuggen auf alle Optimierungen verzichten sollte.

    Der Compiler optimiert nämlich in diesem Fall auch fehlerhaften Code "heraus" (z.B. weil er nie aufgerufen wird) und die Fehler bleiben dann aus.


Anmelden zum Antworten