Maschienencode konvertierung
-
Dann ist aber immer noch das File-Handle offen. Und es gibt Möglichkeiten Dateien so zu öffnen, dass sie kein weiteres Mal geöffnet werden können. Wenn wir aber von Ressourcen sprechen, dann meinen wir nicht nur Dateien. Zum Beispiel bei einem Drucker macht es gar kein Sinn vorher einen neuen Druckauftrag zu versenden, bevor der alte noch nicht abgeschlossen ist.
-
Dein Beispiel ist falsch. Wenn ich mehrere Seiten drucken will, lege ich die Aufträge in eine Auftrags-queue.
-
Paul Müller schrieb:
SeppJ schrieb:
Du hast RAII nicht verstanden.
Geht das schon wieder los?
Bis du es endlich verstehst
. Das ist kein Gefrickel das mal in seltenen Ausnahmefällen funktioniert. Das ist eine grundlegende Technik, die eigentlich immer für alles funktioniert (du magst exotische Ausnahmefälle konstruieren können, aber FileHandles, Drucker und vor allem Arbeitsspeicher gehören nicht dazu!).SeppJ schrieb:
Solche Fälle sollte man gar nicht erst aufkommen lassen.
Dann beschwer dich bei 314159265358979 und sag ihm, dass sein Design scheiße ist.
Ist es auch, denn seine Variablen sind nicht so lokal wie sie sein sollten:
#include <iostream> #include <fstream> #include <iomanip> int main(int argc, char** argv) { { std::ofstream os("exit.bin"); os << '\x90' << std::flush; } // os wird hiernach nie wieder gebraucht, also lokal machen. { std::ifstream is("exit.bin"); unsigned char tmp; is >> tmp; std::cout << std::hex << static_cast<unsigned>(tmp) << std::endl; } // is und tmp werden hiernach nie wieder gebraucht, also lokal machen }Zack, alle Probleme gelöst indem 4 Zeichen eingefügt wurden. Gleichzeitig gezeigt, dass man über die Programmstruktur nachgedacht hat. Und vor allem kann jetzt nirgends mehr irgendwas schiefgehen.
-
Ist das euer ernst mit den Klammern oder ein schlechter Scherz?

-
Nein dein Ansatz ist falsch. Die Auftrags-Queue ist nicht der Drucker, die Auftrags-Queue bedient nur den Drucker. Damit hält sie das Problem von dir fern, indem sie dir die Arbeit abnimmt. Aber nur weil du das Problem nicht mehr siehst, heißt das nicht, dass es nicht prinzipiell da ist.
-
Über den Ansatz mit den Klammern hab ich auch schon nachgedacht. Hab ihn aber wieder verworfen, weil man ja auch noch Variablen gebrauchen könnte, die auf diesem Weg durch ihre Initialisierung in einen anderen Block rutschen.
-
Paul Müller schrieb:
Über den Ansatz mit den Klammern hab ich auch schon nachgedacht. Hab ihn aber wieder verworfen, weil man ja auch noch Variablen gebrauchen könnte, die auf diesem Weg durch ihre Initialisierung in einen anderen Block rutschen.
Was meinst du mit Variablen, die durch ihre Initialisierung in einen anderen Block rutschen?
@314159265358979 :
Natürlich ist der Ansatz ernst gemeint - scopes eingefügt, Objekte werden zerstört wenn sie nicht mehr gebraucht werden und dabei Resourcen freigegeben -> RAII umgesetzt.
-
{ std::ifstream is("exit.bin"); unsigned char tmp; is >> tmp; std::cout << std::hex << static_cast<unsigned>(tmp) << std::endl; } // is und tmp werden hiernach nie wieder gebraucht, also lokal machenWas ist, wenn ich tmp später doch noch brauche? Dann bleibt mir ja gar nichts anderes übrig, als tmp außerhalb des Scopes zu deklarieren. Und damit hätte ich ja kein RAII mehr. Auch wenn RAII in Verbindung mit tmp in jedem Fall verletzt wird, so beschränkt sich die Variante von SeppJ zumindest auf eine minimal mögliche Verletzung.
-
Paul Müller schrieb:
Was ist, wenn ich tmp später doch noch brauche? Dann bleibt mir ja gar nichts anderes übrig, als tmp außerhalb des Scopes zu deklarieren.
Genau.
Und damit hätte ich ja kein RAII mehr.
Wieso nicht?
Faustregel: RAII funktioniert und hilft immer. Gegenbeispiele musst du schon sehr gezielt konstruieren. Hier sehe ich nicht, was du für ein Problem haben könntest.
-
Ich seh den Zusammenhang nicht ganz. Inwiefern würde eine Definition (nicht Deklaration) von tmp im übergeordneten scope (also der main-Funktion) das RAII-Idiom verletzen?
Die STL macht gebrauch von der RAII-Technik - beim file-stream-template wird eben im Destruktor close() aufgerufen. Dann macht es allerdings wenig Sinn, wenn ich die Lebensdauer eines filestream-Objekts unnötig verlänger - im schlimmsten Fall leg ich es global an.
Also versucht man Objekte möglichst lokal zu halten und genau das geschieht hier doch.
-
struct Foo { Foo() Foo(std::istream &); std::istream & operator >> (std::istream &); }; int main() { Foo foo; // Initialisierung { std::cin >> foo; // Zuweisung } Foo bar(std::cin); // Initialisierung }Oder wo ist mein Denkfehler?
-
std::cin ist ein Objekt, kein Typ.
{ std::cin >> foo; // Zuweisung }Hier wird also kein Konstruktor oder Destruktor aufgerufen, folglich findet kein RAII statt.
-
Genau das steht doch dort?
-
Dann schreib doch bitte was dein Beispiel zeigen sollte. So wie du es gemacht hast, macht die Einführung eines weiteren Scopes natürlich keinen Sinn...
-
Es geht ja auch gar nicht um den Scope, sondern um RAII. Sorry wenn dich das verwirrt hat.
-
Paul Müller schrieb:
Es geht ja auch gar nicht um den Scope, sondern um RAII. Sorry wenn dich das verwirrt hat.
Ich sehe auch nicht, was das mit RAII zu tun haben soll. Und die Kommentare helfen nicht. Außerdem compiliert das nicht einmal.
-
Es geht ja auch gar nicht um den Scope, sondern um RAII.
Dein Beispiel hat nur, wie ich erklärt habe, nichts mit RAII zu tun.
RAII ist doch ganz einfach: Im Konstruktor fordere ich Ressourcen an (z.B. mit
new) und im Destruktoren gebe ich die Ressourcen wieder frei (z.B. mitdelete). Da die Destruktoren in C++ deterministisch sind, kann man sicher sein, dass sobald ein Objekt den Scope verlässt, der Destruktor aufgerufen wird und dadurch die Ressourcen freigegeben werden. Nur so kann man dann auch richtige Exceptionsicherheit bekommen.Zur Benutzung von std::fstream::close():
Diese macht nur Sinn, wenn man das Objekt für eine andere Datei wiederverwenden möchte, statt ein neues dafür anzulegen. In so einem Fall muss vorher close() aufgerufen werden, da sonst open() fehlschlägt.
-
So als kurz gesagt ich kann das ganze besser so machen ?
Beispiel 1:
Funktioniert
#include <iostream> #include <fstream> using namespace std; int main() { char save[200] ; unsigned char var; { ofstream file ( "exit.bin" ); file << "\x90"; } // file handle ist geschlossen { ifstream f2 ( "exit.bin" ); f2 >>save; } // f2 handle ist geschlossen var=save[0]; cout<<var<<endl; cout<< hex << static_cast<int>(var); system("PAUSE"); }Beispiel 2:
Ausgabe:
É
90Drücken Sie eine beliebige Taste . . .Funktioniert NICHT die Ausgabe ist falsch !
#include <iostream> #include <fstream> using namespace std; int main() { char save[200] ; unsigned char var; ofstream file ( "exit.bin" ); file << "\x90"; ifstream f2 ( "exit.bin" ); f2 >>save; var=save[0]; cout<<var<<endl; cout<< hex << static_cast<int>(var); system("PAUSE"); }Ausgabe:
0 Drücken Sie eine beliebige Taste . . .
Beispiel 3:
Funktioniert
#include <iostream> #include <fstream> using namespace std; int main() { char save[200] ; unsigned char var; ofstream file ( "exit.bin" ); file << "\x90"; file.close(); ifstream f2 ( "exit.bin" ); f2 >>save; f2.close(); var=save[0]; cout<<var<<endl; cout<< hex << static_cast<int>(var); system("PAUSE"); }Ausgabe:
É
90Drücken Sie eine beliebige Taste . . .
-
Weil du von der File in einen char* einliest, du musst in einen unsigned char einlesen -.-
-
Was ein ctor/dtor ist und wann sie gerufen werden, weiß ich. Ich weiß auch, ohne den Fachbegriff dafür zu wissen, was ich damit anstellen kann. Da bin ich mal so überheblich zu behaupten, man kann auch problemlos selbst drauf kommen. Was mich aber an Resource Acquisition Is Initialization gestört hat, ist dieses Acquisition Is Initialization. Das findet ja nicht statt, wenn ich eine undefinierte Variable hab. Im Gegenzug ist mein Objekt schon initialisiert, wenn ich ein komplexes Gebilde mit ctor habe und erst danach den eigentlichen Inhalt über einen Stream erhalte. In beiden Fällen kann also nicht die Rede von Ressourcenanforderung bei Initialisierung die Rede sein. Andrerseits bleibt auch offen, was genau mit Ressourcen gemeint ist? Der Laie (ich) würde jetzt an die paar Bytes auf den Stack denken. Weil darauf stoßen einem eigentlich alle konventionellen Beispiele zu RAII. Meist bekommt man gezeigt, dass man die Variablen anlegen soll, erst wenn man sie verwendet und das ist es dann. Das deckt sich aber wie geschrieben nicht 100%ig mit der Anforderung, die ich zum Beispiel bei Streams hab, dass das Objekt vorher vorhanden sein muss. Wenn man nach der englischen Wikipedia geht scheint es aber ein alleiniges ctor/dtor Problem zu sein, was dann auch mit eurer Erläuterung sich voll decken würde.