Rückgabewert schlägt fehl!!!!



  • Hi, meine string-Klasse funktionierte bis jetzt ganz gut. Doch jetzt geht das nicht.

    string f() {
      char* test="AUS DER FUNKTION";
      string result("Test");
      return result; 
    }
    
    int main()
    {
    	char* test="TEST;";
    	char test2[]="ZWEITER TEST";
    
    	string str(test);
    	string str2;
    
    	str2=test2;
    
    	std::cout<<str._char()<<std::endl;
    	std::cout<<str.len()<<std::endl;
    
    	std::cout<<str2._char()<<std::endl;
    	std::cout<<str2.len()<<std::endl;
    
    	str=str2;
    
    	std::cout<<str._char()<<std::endl;
    	std::cout<<str.len()<<std::endl;
    
                      // 
             str=f(); // FEHLER !!!!!
    	std::cout<<str._char()<<std::endl;
    	std::cout<<str.len()<<std::endl;
    
    	return 0;
    }
    

    wenn ich die Funktion f() benutze stürzt das Programm wieder ab. Hat das wieder mit flachen Kopien und Co. zu tun? Ich habe schon einiges ausprobiert doch nichts hat geholfen. Weiss einer wie ich das richtig mache.

    Danke, cu



  • Hi, ich bins wieder.

    Ich verstehe nicht warum so was funktioniert.

    int f()
    {
     int a=10;
     return a;
    }
    

    jedoch das nicht

    string f()
    {
      string temp;
      temp="Test";
      return temp;
    }
    

    PS: Zusatzinfo. string ist eine eigene Klasse.

    siehe dazu:

    http://www.c-plusplus.net/forum/viewtopic.php?t=65127
    http://www.c-plusplus.net/forum/viewtopic.php?t=64810&start=0



  • hast du einen copy-ctor und zuweisungsoperator definiert für string.

    wenn's nur für lernzwecke sein soll ist es ok, aber ansonsten verwende aus der stl den string.

    cu



  • Also ich komme nicht zur Lösung. Mein Gehirn ist stehen geblieben.

    Ich bin so frei und möchte den Quellcode hier reinstellen. Es ist ein übler hack weil vieles gelöscht und wieder dazu gekommen ist. Ich hoffe das einer der sich damit besser aukennt mir sagen kann wie ich das richtig mache.

    Hier die cpp-Datei:

    #include"mystring.h"
    
    namespace xx
    {
    	//  Konstruktor
    	    string::string ()
    		{
    			_string = NULL;
    		   std::cout<<"Konstruktor 1\n";
    		}
    
    		string::string (char* t)
    		{
    		   std::cout<<"Konstruktor 2\n";
    			int l;
    
    			l=len(t)+1;
    
    			_string=new char[l];
    
    			l=0;
    
    			while(t[l])
    			{
    				_string[l]=t[l];
    				l++;
    			}
    			_string[l]='\0';
    		}
    
    	//  Destruktor
    		string::~string()
    		{
               if(_string)
    			delete[] _string;
    		   std::cout<<"Destruktor\n";
    		}
    
    	//  Zeiger auf char zurück geben
    		char* 
    		string::_char(void){
    			return _string;}
    
    	//  Länge des Strings 
    		int 
    		string::len(){
    			if(_string)
    			{
    				int l=0;
    				while (_string[l]){l++;}
    				return l;
    			}
    			return 0;}
    
    	//  Länge des Strings
    		int 
    		string::len(const char* s){
    			if(s)
    			{
    				int l=0;
    				while (s[l]){l++;}
    				return l;
    			}
    			return 0;}
    
    	//  a Zeichen von links als string
    		string 
    		string::left(int a)
    		{
    			char* t = new char[a+1];
    			int b=0;
    			a--;
    			while(b<=a){ 
    				t[b]=_string[b]; 
    				b++;} 
    			t[b]='\0';
    			string st(t);
    			delete[] t;
    			return st;}
    
    	//  a Zeichen von rechts als string
    		const string 
    		string::right(int a){
    			int b=0; int l;
    			char* t= new char[a+1];
    			l=len()-a;
    			while(_string[b]){
    				t[b]=_string[l+b];
    				b++;}
    			t[b]='\0';
    			string st(t);
    			delete[] t;
    			return st;}
    
    	//  a Zeichen ab b als string
    		string 
    		string::mid(int a, int b){
    			int cnt=0;
    			char* t=new char[a+1];
    			a--;
    			while(cnt<=a){
    				t[cnt]=_string[cnt+b-1];
    				cnt++;}
    			t[cnt]='\0';
    			string st(t);
    			delete[] t;
    			return st;}
    
    	//  Prüft ob char* t ab a im string enthalten ist
    		int 
    		string::instr(char* t, int a){
    			int	l = len(t)-1;int b = 0;
    			if(a<0)return 0;
    			while(_string[a+1]){
    				while(t[b]){
    					if(t[b]!=_string[a+b]) break;
    					b++;
    					if(b==l) return a+1;}
    				b=0;
    				a++;}
    			return 0;}
    
    	//  Prüft ob string t ab a in string enthalten ist
    		int 
    		string::instr(string _st, int a){
    			char* t=_st._char();
    			int	l = len(t)-1; int b = 0;
    			if(a<0) return 0;
    			while(_string[a+1]){
    				while(t[b]){
    					if(t[b]!=_string[a+b]) break;
    					b++;
    					if(b==l) return a+1;}
    				b=0;
    				a++;}
    			return 0;}
    
    		const string& 
    		string::operator=(const char* t)
    		{	
    		   std::cout<<"Operator 1\n";
    
    			if(_string)
    				delete[] _string;
    
    			int l;
    
    			l=len(t)+1;
    
    			_string=new char[l];
    
    			l=0;
    
    			while(t[l])
    			{
    				_string[l]=t[l];
    				l++;
    			}
    			_string[l]='\0';
    
    			return *this;
    		}
    
    		const string& 
    		string::operator=(const string& st)
    		{
    		   std::cout<<"Operator 2\n";
    
    			if(_string)
    				delete[] _string;
    
    			char* t=st._string;
    
    			string temp(t);
    
    			int l;
    
    			l=len(temp._char())+1;
    
    			_string=new char[l];
    
    			l=0;
    
    			while(t[l])
    			{
    				_string[l]=t[l];
    				l++;
    			}
    			_string[l]='\0';
    
    			return *this;
    		}
    }
    
    using namespace xx;
    
    string f() {
      char* test="AUS DER FUNKTION";
    
      string result=test;
      std::cout<<result._char()<<"\n";
    
      return result; 
    }
    
    int main()
    {
    	char* test="TEST;";
    	string str(test);
    	string str2;
    	char test2[]="ZWEITER TEST";
    	str2=test2;
    
    	std::cout<<str._char()<<std::endl;
    	std::cout<<str.len()<<std::endl;
    
    	std::cout<<str2._char()<<std::endl;
    	std::cout<<str2.len()<<std::endl;
    
        f();
    
    	str=str2;//.right(2);
    
    	std::cout<<str._char()<<std::endl;
    	std::cout<<str.len()<<std::endl;
    
        str="DREI";//str.right(2);//f(); // FEHLER !!!!!
    	std::cout<<str._char()<<std::endl;
    	std::cout<<str.len()<<std::endl;
    
    	return 0;
    }
    

    und die .h Datei

    #include"iostream"
    
    namespace xx
    {
    	class string
    	{
    	private: 
    		char* _string;
    		int len(const char* s);
    	public:
    		string ();
    		string (char* string);
    		~string();
    		char* _char(void);
    		string left(int a);
    		const string right(int a);
    		string mid(int a, int b);
    		int len();
    		int instr(char* t, int a);
    		int instr(string _st, int a);
    
    		const string& operator=(const char*);
    
    		const string& operator=(const string&);
    
    		bool operator==(string st)
    		{
    			if (len()!=st.len())
    				return false; 
    			if(instr(st._char(),0)==0)return false; 
    				return true;
    		}
    
    		bool operator==(char* t)
    		{
    			if (len()!=len(t))return false; 
    			if(instr(t,0)==0)return false; 
    			return true;
    		}
    	};
    }
    

    Ich habe das mal in den namespace xx gepackt um keine Probleme mit dem string aus der STL zu bekommen. Das ganze ist als Übung gedacht.



  • als erstes würde ich die string repräsentation in einer innerclass verbergen (struct)
    2 sollten die kopie operationen minimiert werden. erreicht man durch copy on write.
    3. es gibt einen debugger.
    4. wieso liefert dein zuweisungsoperator ne konstante referenz zurück
    5. was ist die fehlermeldung? speicherzugriffsfehler?
    6. speichere die länge in einer int variablen ab, und frag sich nicht immer ab.
    7. funktioniert eine normale zuweisung?



  • zu 1. Wie meinst du das?

    zu 2. Was bedeutet copy on write?

    zu 3. ich weiss

    zu 4. Weiss ich nicht. Hab ich mal so gemacht. Ich habe es jetzt geändert.
    Muss noch vom vielen rumprobieren übriggeblieben sein.

    zu 5. MELDUNG -> Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

    zu 6. Mach ich.

    zu 7. Ja.

    PS: Ich habe festgestellt das geht auch nicht.

    //  a Zeichen von rechts als string
    string string::right(int a)
    {
    	int b=0; int l;
    	char* t= new char[a+1];
    	l=len()-a;
    	while(_string[b]){
    		t[b]=_string[l+b];
    		b++;
                      }
    	t[b]='\0';
    	string st(t);
    	delete[] t;
    	return st;}
    

    Was ich nicht verstehe ist. In dieser Methode wird doch ein Objekt string erstellt. Dieser existiert solange wie die Funktion läuft. Am ende gebe ich string zurück. Und da wird das Objekt vom Destruktor zerstört. Wie löst man so ein Problem.



  • du brauchst einen Referenzzähler und die ganzen String-spezifische Daten packt man normalerweise in eine (nested) Klasse bzw. Struktur. In der eigentlichen Klasse, wird nur der Zeiger auf diese Struktur gespeichert.
    http://www.memorymanagement.org/glossary/r.html#reference.counting



  • du löscht irgendwo den speicher mit delete, den du nicht mit new alloziert hast.
    (lt. der fehlermeldung)
    cu



  • Der Copy-Ctor fehlt, deswegen wird beim return ne flache Kopie gemacht... und das lokale Objekt gibt den Speicher frei.

    @grenouille_unreg: COW ist für strings wohl nicht so das tollste. Siehe z.B. Sutter: MEC++

    MfG Jester



  • @jester: na toll du wirfst mir irgebdwas hin und gibts mir nicht mal ne quelle(link) an. erläutere mal die neg. seiten und gib mal ne bessere variante an. würde mich jetzt mal interessieren. hab den sutter auch net da.

    cu



  • LOL 🙂
    ich hab im moment genau dasselbe problem! allerdings hab ich mein glück schon mit einem copy-konstruktor versucht, was allerdings auch in einem segfault endet. naja, werd wohl mal weiter in sachen copy-c'tor 'forschen'... 😉

    falls jemand von euch einen netten link hätte wäre das natürlich auch nicht schlecht. 😃

    ciao, cypoc



  • irgendwie versagt bei mir alles, was sich copy-c'tor nennt... 😞

    hier mal ein bissl code:

    /** main.cpp **/
    
    int main( int argc, char* argv[] )
    {
        crazyConfig *config;
        config = new crazyConfig( "./log/config.cfg" );
        config->readConfig( );
    
        configItem *item;
    
        int cnt = 0;
    
        do
        {
               item = new configItem( config->getConfigItem( cnt ) );
               cnt++;
               cout << item->getItemName( ) << " = " << item->getItemValue( ) << endl;
               delete item;
        } while( cnt<7 );
    
        delete config;
    
        return 0;
    }
    

    hier der copy-c'tor:

    /** copy-konstruktor **/
    
    configItem::configItem( const configItem &item )
    {
    	cout << "start copy-construktor" << endl;
    	/** hier tritt ( scheinbar ) der segfault auf  **/
    	itemName = item.getItemName( );
    	itemValue = item.getItemValue( );
    	itemID = item.getItemID( );
    	/** das hier wird nicht mehr angezeigt **/
    	cout << "ende copy-construktor" << endl;
    }
    

    und als letztes noch die funktion crazyConfig::getConfigItem, mit der der copy-c'tor aufgerufen wird:

    /** crazyConfig::getConfigItem( ... ) **/
    
    configItem &crazyConfig::getConfigItem( unsigned int id )
    {
    	for( it=new_configItem.begin( ); it!=new_configItem.end( ); it++ )
    	{
    		if( ( *it )->getItemID( ) == id )
    	               return *( *it );
    	}
    }
    

    die funktion crazyConfig::getConfigItem( ... ) hab ich schon mehrmals verändert hinsichtlich rückgabewert und co. der segfault tritt immer an der gleichen stelle im code auf ( siehe kommentar ). 😞

    was mach ich da falsch? 😕

    ciao, cypoc


Anmelden zum Antworten