Tricky C++

Fragen und Neuigkeiten zu C / C++, C#, Java, (X)HTML, PHP, SQL, Perl und weiß Gott was noch alles!
Forumsmitglieder sind herzlich eingeladen hier ihre Arbeiten und Projekte zu präsentieren
Antworten
Benutzeravatar
LX
Administrator
Administrator
Beiträge: 3044
Registriert: 6. April 2002 22:32
Wohnort: Schwindegg
Kontaktdaten:

Tricky C++

Beitrag von LX »

Das hab ich gerade in unserem VInf-Forum gefunden (und natürlich auch geknackt ^^ ) und fands echt gut!

Bin gespannt wer von euch dieses kleine Rätsel lösen kann:

Code: Alles auswählen

#include <iostream>

using namespace std;

class bugged_string
{
   char *str;
public:
   bugged_string(const char *in)
   {
      str = new char[strlen(in) + 1];
      strcpy(str, in);
   }

   ~bugged_string()
   {
      delete [] str;
   }

   char* get()
   {
      return str;
   }
};

void tu_nix(bugged_string blubb)
{
   // tut absolut nichts (sollte man meinen :-) )
}

int main()
{
   bugged_string test("Hallo");
   cout << test.get() << endl;
   tu_nix(test);
   char c[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
   cout << test.get() << endl;

   // auf enter warten:
   cin.clear();
   cin.ignore(cin.rdbuf()->in_avail());
   cin.get();
}



wenn man sich das ganze anschaut sollte man meinen das Programm gibt zweimal "Hallo" aus und beendet ohne Fehler.

Tut es aber nicht! Auf meinem Laptop schaut die Ausgabe so aus:

Code: Alles auswählen

Hallo
¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■
¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■
¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■
¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¯■¶

(Die Ausgabe wird auf anderen Systemen und mit anderen Compilern wahrscheinlich anders aussehen, mit sehr viel Glück funktioniert das Programm vielleicht sogar)

Was passiert hier?


Viel Spaß beim Rätseln!
Bild
Benutzeravatar
Worm
Grimoire
Beiträge: 403
Registriert: 19. Juli 2004 04:35
Wohnort: München

Beitrag von Worm »

Also, ein teil des problems hab ich glaub ich schon erkannt.
[spoiler]
Und zwar liegt das Problem daran, das ein echter copy-konstruktor fehlt.
Bei void tu_nix wird also der default copy-konstruktor verwendet, der alle werte 1:1 kopiert, nennen wir den kopierten pointer des strings ma str2.
So, wenn jetzt void tu_nix beendet wird, wird für das Objekt blubb der Destruktor aufgerufen, was soviel heißt wie delete [] str2;
da aber *str=*str2 ist (default copy konstruktor) wird der inhalt von *str gelöscht.
Wie es dann aber zur ausgabe am Bildschirm kommt weiß ich auch net :/
[/spoiler]
Manchmal kann man eine tödliche Bombe einfach nicht loswerden.
trykyn
Administrator
Administrator
Beiträge: 905
Registriert: 6. April 2002 23:00
Wohnort: Haimhausen
Kontaktdaten:

Beitrag von trykyn »

[spoiler]bin auch soweit gekommen das in tu_nix das kopierte objekt wieder gelöscht wird , und das offensichtlich auf den selben speicher zeigt wie das original (wie das mit default cpy ctors zu tun hat hatte ich allerdings keine ahnung...)

und zur ausgabe am bildschirm:
da nun auf irgendeinen gelöschten bereich gezeigt wird kann da drin stehn was will... bis halt irgendwann n \0 kommt[/spoiler]

Code: Alles auswählen

char c[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

ist nur zur verwirrung oder?
Benutzeravatar
LX
Administrator
Administrator
Beiträge: 3044
Registriert: 6. April 2002 22:32
Wohnort: Schwindegg
Kontaktdaten:

Beitrag von LX »

:top: alles richtig, also wirklich alles :)

[spoiler]ausser das du schreiben solltest str=str2 und nich *str=*str2 ^^, aber ansonsten stimmt jede aussage[/spoiler]

sehr gut, hab nich damit gerechnet =)
Bild
Benutzeravatar
Worm
Grimoire
Beiträge: 403
Registriert: 19. Juli 2004 04:35
Wohnort: München

Beitrag von Worm »

Das sollte net korrektes c++ sein sondern nur für "der Bereich auf den str is derselbe wie der, auf den str2 zeigt" die kurzform sein :)
Ich weiß, bin schreibfaul :)

[edit]
Aber ein sehr schönes Beispiel dafür, dass das, was in so manchen tutorials immer steht, und zwar dass man den copykonstruktor immer dann schreiben muss, wenn man auch den normalen konstruktor und destruktor schreibt wirklich wichtig ist :)

[nochn edit]
Das Rätsel is aber genial, hat spaß gemacht zu knobeln :)
Manchmal kann man eine tödliche Bombe einfach nicht loswerden.
Benutzeravatar
LX
Administrator
Administrator
Beiträge: 3044
Registriert: 6. April 2002 22:32
Wohnort: Schwindegg
Kontaktdaten:

Beitrag von LX »

ne, wenn dus so machst dann würd n ganz anderes ergebnis rauskommen,
*str = *str2 := wertkopie (r-value)
str = str2 := adresskopie (l-value)
Bild
Benutzeravatar
Worm
Grimoire
Beiträge: 403
Registriert: 19. Juli 2004 04:35
Wohnort: München

Beitrag von Worm »

Jajajaja :/

Ich glaub ich weiß was das char c[] blabla soll
Und zwar wird der speicherplatz mit delete [] freigegeben, aber der speicher nicht überschrieben, d.h. das alte "Hallo" ist noch gespeichert.
Wenn er jetzt das neue array speichert wird normalerweise derselbe speicher wie zuvor (da jetzt freigegeben) zugewiesen, und das stellt sicher, das in den speicherbereich auf den str zeigt nix sinnvolles mehr stehen kann.

Würd ich jetzt mal vermuten :)
Manchmal kann man eine tödliche Bombe einfach nicht loswerden.
Benutzeravatar
LX
Administrator
Administrator
Beiträge: 3044
Registriert: 6. April 2002 22:32
Wohnort: Schwindegg
Kontaktdaten:

Beitrag von LX »

char cc[] wird allerdings auf dem stack alloziert..
vielleicht macht er bei manchen compilern lustige dinge aber bei allen die ich bisher gesehen hab wars völlig unerheblich ob er da war.
Bild
Benutzeravatar
Worm
Grimoire
Beiträge: 403
Registriert: 19. Juli 2004 04:35
Wohnort: München

Beitrag von Worm »

War ja nur ne vermutung, hast ja recht :/
Manchmal kann man eine tödliche Bombe einfach nicht loswerden.
Benutzeravatar
LX
Administrator
Administrator
Beiträge: 3044
Registriert: 6. April 2002 22:32
Wohnort: Schwindegg
Kontaktdaten:

Beitrag von LX »

resistance is futile :P
Bild
Benutzeravatar
LX
Administrator
Administrator
Beiträge: 3044
Registriert: 6. April 2002 22:32
Wohnort: Schwindegg
Kontaktdaten:

Re: Tricky C++

Beitrag von LX »

Gerade die Werbung in der c't gesehn, aber kann sie leider nicht versuchen zu knacken da mir ein c-compiler fehlt und im kopf bin ich zu faul dazu ;)
GDATA
C++ -Entwickler für Antivirensoftware (m/w)

Code: Alles auswählen

std::string gdata::decrypt(std::string m, unsigned char key)
{
	std::rotate(m.begin() + m.length() - key, m.end());
	std::stringstream ss;
	for (std::string::iterator c=m.begin(); c!=m.end(); c++) {
		ss << (char)(*c) - key);
	}
	return ss.str();
}

std::cout << gdata::decrypt("F%Fsyn[nwzxL%IFY", key) << std::endl;
Geknackt? Dann schicken sie bitte die Lösung .... etc.
hf ;)

aber is ja nich schwer zu brute-forcen...
Bild
trykyn
Administrator
Administrator
Beiträge: 905
Registriert: 6. April 2002 23:00
Wohnort: Haimhausen
Kontaktdaten:

Re: Tricky C++

Beitrag von trykyn »

die Lösung lautet "G DATA AntiVirus"

übrigens ohne compiler gelöst ;)
Antworten