Seite 152 von 255
Re: Jammer-Thread
Verfasst: 12.04.2016, 16:34
von Alexander Kornrumpf
Krishty hat geschrieben:@antisteo: Ja; klar. Spätestens, wenn die Scopes unterschiedlich große Brocken allokieren und dazwischen andere Variablen sitzen, beginnen einfache Algorithmen zu fragmentieren.
Das meinte ich übrigens (@Spiele Programmierer) mit dem gelöschten Einwand "dann wäre es ein Heap". Aber ich war dann selbst verunsichert ob das jemals passieren kann.
Nein. Visual C++ erlaubt’s trotzdem und tut weitestgehend, was du erwarten würdest.
Weird.
Re: Jammer-Thread
Verfasst: 12.04.2016, 16:39
von Krishty
Alexander Kornrumpf hat geschrieben:Das meinte ich übrigens (@Spiele Programmierer) mit dem gelöschten Einwand "dann wäre es ein Heap". Aber ich war dann selbst verunsichert ob das jemals passieren kann.
Unter der Haube ist das eh kein richtiger Stack, denn der Compiler vergrößert den Stapel nur einmal beim Betreten der Funktion (und nicht jedes Mal, wenn eine Variable angelegt wird). Die Variablen werden auch gern mal umsortiert usw. Es sieht nur nach außen aus wie ein Stapel, weil sich das Frontend an die Lebenszeiten aus dem Quelltext hält.
Nein. Visual C++ erlaubt’s trotzdem und tut weitestgehend, was du erwarten würdest.
Weird.
Naja; nützlich (für Fehlerverarbeitung à la
goto fail.) So lange da kein Konstruktor oder Destruktor läuft, sondern nur native Datentypen angelegt werden (die eh uninitialisiert sind, so lange man's nicht explizit hinschreibt), sehe ich auch nicht ein, dass das verboten sein sollte.
Re: Jammer-Thread
Verfasst: 12.04.2016, 16:47
von Alexander Kornrumpf
Nochmal spezifischer: Kann / darf der Compiler (Optimizer?) zwischen gotos unterscheiden die den Scope verlassen und solchen die es nicht tun?
Code: Alles auswählen
{
int foo = 0;
goto bar;
int baz =0; //wird wahrscheinlich wegoptimiert
bar:
++foo; //foo muss hier noch allokiert sein. foobar darf es nach deiner Logik nicht sein.
}
{
int foobar = 0;
//mach irgendwas damit foobar nicht wegoptimiert wird
goto bar;
//mach irgendwas damit nicht offensichtlich ist, dass der scope hier endet, z. B.
foobaz:
int baz =0;
//mach was mit baz. Es könnte einen Sprung an foobaz geben. Ist foobar allokiert oder nicht?
}
Re: Jammer-Thread
Verfasst: 12.04.2016, 17:04
von Spiele Programmierer
Der Speicherplatz für lokale Variablen wird für gewöhnlich am Anfang der Funktion allokiert und nicht auf Blocklevel.
Das Überspringen der Variablendeklaration ist also kein Problem. Das Überspringen der Initialisierung allerdings schon.
Re: Jammer-Thread
Verfasst: 12.04.2016, 17:07
von Alexander Kornrumpf
Spiele Programmierer hat geschrieben:Der Speicherplatz für lokale Variablen wird für gewöhnlich am Anfang der Funktion allokiert und nicht auf Blocklevel.
Das ist genau das was Krishty nicht will?! Hab ich was total falsch verstanden?
Re: Jammer-Thread
Verfasst: 12.04.2016, 17:23
von Spiele Programmierer
Kristhy möchte, dass sich lokale Variablen, dessen Scope sich nicht überschneidet, den selben Speicherplatz teilen können.
Das hat nichts damit zu tun, das jede Variable einzeln allokiert wird. Es wird einmal allokiert und jede lokale Variable verwendet einen ihr zugewiesenen Stackbereich daraus. Wenn zwei lokale Variablen nicht gleichzeitig auftreten, können sie sich sie einen Bereich teilen.
Re: Jammer-Thread
Verfasst: 12.04.2016, 17:27
von Alexander Kornrumpf
Spiele Programmierer hat geschrieben: Wenn zwei lokale Variablen nicht gleichzeitig auftreten, können sie sich sie einen Bereich teilen.
Ja. Um meine ursprüngliche Vermutung, dass das Problem äquivalent zu Allokation und Deallokation im Freispeicher (vulgo: Heap) ist, zu prüfen, versuche ich jetzt herauszufinden wieviel man mit goto kaputt machen kann.
Re: Jammer-Thread
Verfasst: 12.04.2016, 17:29
von Spiele Programmierer
Ja mit "goto" kann man die Optimierung verhindern.
Ohne "goto" bzw. andere teilweise problematische Konstrukte sollte es aber funktionieren. ;-)
Re: Jammer-Thread
Verfasst: 12.04.2016, 17:30
von Alexander Kornrumpf
Spiele Programmierer hat geschrieben:Ja mit "goto" kann man das teilweise untergraben.
Ohne "goto" bzw. andere teilweise problematische Konstrukte sollte es aber funktionieren. ;-)
Deckt sich mit meiner Einschätzung.
Re: Jammer-Thread
Verfasst: 12.04.2016, 17:33
von Krishty
goto bedeutet nicht, dass der Compiler da direkt einen Sprungbefehl einbaut. Er *muss* sogar die alten Variablen zerstören (falls sie Destruktoren besitzen), um standardkonform zu bleiben. Also ist da eh Code zwischen. Darum sehe ich nicht, was da untergraben werden sollte.
Re: Jammer-Thread
Verfasst: 12.04.2016, 17:36
von Alexander Kornrumpf
Krishty hat geschrieben:goto bedeutet nicht, dass der Compiler da direkt einen Sprungbefehl einbaut. Er *muss* sogar die alten Variablen zerstören, um das Programm funktionsfähig zu halten. Darum sehe ich nicht, was da untergraben werden sollte.
Ich habe goto noch nie verwendet und weiß nicht wie es sich verhält. Deswegen frage ich ja.
EDIT: Nochmal in Zeitlupe. Worüber wir uns wahrscheinlich einig sind:
Wenn sich alle so verhalten, wie Nikolaus Wirth es gewollt hätte, dann sind "post-scope" _genau_ die gleichen Teile des Stacks in Verwendung (um nicht Allokiert zu sagen) wie "pre-scope" und alles was "in-scope" bezüglich zusätzlicher Verwendung des Stack passiert ist, hat über (unter) einer bestimmten Adresse stattgefunden. Dieser Bereich (über/unter der Adresse) ist jetzt wieder verwendbar. Das Problem ihn wiederzuverwenden ist trivial. In einem Moment geistiger Umnachtung hatte ich das zunächst nicht erkannt bzw. vergessen.
Wenn aber nicht alles so läuft wie Nikolaus With sich das vorstellt, kann in-scope Ausgangspunkt oder Ziel eines Sprungs sein, und dann muss man "irgendwas" nicht triviales machen über das ich nie nachgedacht habe, weil goto ja eh böse ist. Was ist "irgendwas", as defined by C++, und kann es die o. g. Wirthsche Invarianz kaputtmachen?
Erschwerend kommt hinzu, dass selbst wenn es konzeptionell so funktionieren würde, wie Wirth es sich vorstellt, ist es, wie ihr beide angemerkt habt, tatsächlich nicht so _implementiert_. Ist es also vielleicht ein anderweitig nützliches Detail der Implementierung, was die o. g. Invarianz zerstört? Sprich: ein Trade-Off?
Re: Jammer-Thread
Verfasst: 12.04.2016, 18:06
von Krishty
Alexander Kornrumpf hat geschrieben:Erschwerend kommt hinzu, dass selbst wenn es konzeptionell so funktionieren würde, wie Wirth es sich vorstellt, ist es, wie ihr beide angemerkt habt, tatsächlich nicht so _implementiert_. Ist es also vielleicht ein anderweitig nützliches Detail der Implementierung, was die o. g. Invarianz zerstört? Sprich: ein Trade-Off?
Trade-off in der Entwicklungszeit? Es gab ja letztens diesen tollen Artikel eines Entwicklers, dass Visual C++ darauf ausgelegt war, in 128 KiB RAM zu laufen, und deshalb möglichst wenig Zustand mitschleppt (u.a. Code erzeugt, bevor die Funktion zu ende geparst ist). Vielleicht deshalb bloß ein
int mit
„bisher benötigte Stack-Größe“ und jede Variable addiert einfach auf. Was anderes kann ich mir nicht vorstellen.
Re: Jammer-Thread
Verfasst: 12.04.2016, 18:10
von Alexander Kornrumpf
Krishty hat geschrieben:Alexander Kornrumpf hat geschrieben:Erschwerend kommt hinzu, dass selbst wenn es konzeptionell so funktionieren würde, wie Wirth es sich vorstellt, ist es, wie ihr beide angemerkt habt, tatsächlich nicht so _implementiert_. Ist es also vielleicht ein anderweitig nützliches Detail der Implementierung, was die o. g. Invarianz zerstört? Sprich: ein Trade-Off?
Trade-off in der Entwicklungszeit? Es gab ja letztens diesen tollen Artikel eines Entwicklers, dass Visual C++ darauf ausgelegt war, in 128 KiB RAM zu laufen, und deshalb möglichst wenig Zustand mitschleppt (u.a. Code erzeugt, bevor die Funktion zu ende geparst ist). Vielleicht deshalb bloß ein
int mit
„bisher benötigte Stack-Größe“ und jede Variable addiert einfach auf. Was anderes kann ich mir nicht vorstellen.
Was war nochmal der Grund für den For-Scope Bug in Visual C++ 6? War das die Geschichte?
Re: Jammer-Thread
Verfasst: 12.04.2016, 18:12
von Krishty
Alexander Kornrumpf hat geschrieben:Was war nochmal der Grund für den For-Scope Bug in Visual C++ 6? War das die Geschichte?
Vielleicht war das mit dem
for auch ein „Feature“ um Quelltext möglichst unportierbar zu anderen Compilern zu machen (mit Internet Explorers HTML haben sie es ja zu ähnlicher Zeit auch so gemacht). Falls du Quellen mit Erklärungen findest, poste sie bitte; mich interessiert sowas sehr :)
Re: Jammer-Thread
Verfasst: 12.04.2016, 19:10
von Spiele Programmierer
Darum sehe ich nicht, was da untergraben werden sollte.
Du hast recht. Woran ich dachte, geht nicht.
Re: Jammer-Thread
Verfasst: 14.04.2016, 13:35
von Jonathan
Re: Jammer-Thread
Verfasst: 14.04.2016, 13:59
von Jonathan
Code: Alles auswählen
else (WIN32)
if ( USING_GNU_C AND NOT APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DM_PI=3.14159265358979323846" )
Jetzt werden also schon CMake-Skripte benutzt um den Wert von
\($\pi$\) festzulegen? Das kann doch einfach niemand mehr für eine gute Idee halten, oder?
Re: Jammer-Thread
Verfasst: 14.04.2016, 14:24
von dot
Nun, das Problem fangt in dem Moment an, wo CMake benutzt wird... :P
Re: Jammer-Thread
Verfasst: 15.04.2016, 13:07
von Jonathan
Ich mach hier einfach mal weiter...
Code: Alles auswählen
# This enforces a particular version of CMake that we require to process the script files
# properly.
cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)
# As of CMake 2.6 policies were introduced in order to provide a mechanism for
# adding backwards compatibility one feature at a time. We will just specify
# that all policies will use version 2.6 symantics.
cmake_policy(VERSION 2.6)
Ich bin mir nicht 100%ig sicher, aber ich glaube, die haben gerade erst explizit mindestens Version 2.8 verlangt, nur um direkt danach in den Kompatibilitätsmodus zu 2.6 zu schalten. Egal was für einen obskuren Grund es dafür auch geben mag, sollte man doch trotzdem irgendwie einsehen, dass das keine Gute Lösung sein kann...
Re: Jammer-Thread
Verfasst: 15.04.2016, 14:50
von dot
Jonathan hat geschrieben:Egal was für einen obskuren Grund es dafür auch geben mag, sollte man doch trotzdem irgendwie einsehen, dass das keine Gute Lösung sein kann...
Du musst bedenken: Die verwenden schon CMake, damit isses eigentlich eh schon egal... :P
Re: Jammer-Thread
Verfasst: 15.04.2016, 22:39
von Chromanoid
RoboVM Winding Down
https://robovm.com/robovm-winding-down/
Ich hab's nie benutzt, fand aber die Technologie spannend. Schon echt ne klassische Tech-Geschichte, Xamarin kauft RoboVM, Microsoft kauft Xamarin, RoboVM wird abgesägt.
Re: Jammer-Thread
Verfasst: 24.04.2016, 23:47
von Krishty
Nachtrag zu der lokale-Variablen-teilen-sich-Speicher-Geschichte von letztens:
Alexander Kornrumpf hat geschrieben:Ist es also vielleicht ein anderweitig nützliches Detail der Implementierung, was die o. g. Invarianz zerstört? Sprich: ein Trade-Off?
Vielleicht haben sie das so gemacht weil ihnen sonst einfach zu viel Code kaputtgeht. Hier ist Quelltext aus
dem Microsoft-Beispiel, wie man einen Shell Handler für Thumbnail-Erzeugung registriert:
Code: Alles auswählen
if (*pszFileType == L'.')
{
wchar_t szDefaultVal[260];
hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
sizeof(szDefaultVal));
// If the key exists and its default value is not empty, use the
// ProgID as the file type.
if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
{
pszFileType = szDefaultVal;
}
}
// Create the registry key
// HKCR\<File Type>\shellex\{e357fccd-a995-4576-b01f-234630154e96}
hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath),
L"%s\\shellex\\{e357fccd-a995-4576-b01f-234630154e96}", pszFileType);
Beobachtet mal genau, was mit dem Inhalt von
szDefaultVal passiert sein könnte, sobald er in der letzten Zeile durch
pszFileType in den String geschrieben wird.
Da graust es einen echt, denn sicher ein Viertel aller Thumbnail Handlers auf diesem Planeten wurde nach diesem Beispiel gebaut. Der Code ist ganz klar kaputt, aber Visual C++ warnt nicht. Vielleicht hatten sie die Optimierung an irgendeiner Stelle eingebaut; dann in ihren Tests zwanzigtausend Abstürze wegen Müll in Variablen gekriegt (schließlich wird ganz Windows mit Visual C++ kompiliert, und da kommt Code wie oben sicher öfter vor), und das vertagt, bis sich die Code-Qualität verbessert hat.
Re: Jammer-Thread
Verfasst: 25.04.2016, 10:10
von Alexander Kornrumpf
Erscheckend plausibel. Vielleicht wäre es besser, wenn man Pointer in den Stack grundsätzlich nur zum Zweck der Parameterübergabe kopieren dürfte?!
Re: Jammer-Thread
Verfasst: 25.04.2016, 15:03
von Spiele Programmierer
Der Vorschlag überzeugt mich nicht, weil er viele sehr wichtige und legitime Anwendungsfälle verhindert.
Mein Gegenvorschlag lautet "Rust". ;)
Re: Jammer-Thread
Verfasst: 25.04.2016, 17:02
von Jonathan
Ich habe eine Millionen Jahre lang gesucht und zweimal CMake neu installiert, weil mein Projektname ein Leerzeichen enthielt, was eine völlig merkwürdige Fehlermeldung produzierte... ("CMake Error: Could not find cmake module file: CMakeDetermineDemoCompiler.cmake")
Re: Jammer-Thread
Verfasst: 28.04.2016, 13:54
von Krishty
Mein Thumbnail Handler ist 90 KiB groß. 79 KiB davon entfallen auf die Visual-C++-CRT, die überzeugt ist, folgende Dinge gehörten in mein Programm obwohl ich keinen Gebrauch davon mache:
- log10() (fast 2 KiB)
- parse_command_line(), expand_argument_wildcards(), common_expand_argv_wildcards(), usw – obwohl ich eine DLL kompiliere(!)
- memcpy – ich sehe ein, dass man das manchmal zur Initialisierung braucht; aber nicht, dass es mit 1 KiB größer ist als viele meiner Image Loader
- _raise_exc_ex(), _seh_filter_exe() und weitere Ausnahmebehandlungsroutinen – obwohl Exceptions in den Projekteinstellungen abgeschaltet sind und ich kein SEH nutze
- setmbcp_internal(), write_text_utf8_nolock(), und weiterer Locale-Dreck – obwohl ich keine stdio oder C++-I/O nutze
- __report_gsfailure() – obwohl Security Checks deaktiviert und Security Cookies durch Compiler-Switch ausgeknipst sind
- Rund fünfzig Funktionen betreffend Locks und Mutexe – obwohl ich nichts in Richtung Multithreading verwende außer _InterlockedIncrement() & Co.
- Etliche KiB unkenntlichen Mülls aus einer gewissen winapi_thunks.obj
Ich muss also dringend wieder anfangen, meine eigene CRT zu schreiben. Wirklich – fuck that shit.
Re: Jammer-Thread
Verfasst: 28.04.2016, 15:12
von Spiele Programmierer
Ist es nicht Aufgabe es Linkers, unbenützte Funktionen zu entfernen?
Werden die genannten Routinen auf subtile Art doch irgendwo benützt oder ist der Linker wirklich so ein Schrott?
Re: Jammer-Thread
Verfasst: 28.04.2016, 15:18
von Krishty
Ich vermute folgendes:
- Visual C++ baut für alle globalen Variablen Initializer.
- Diese Initializer werden bei Programmstart durch die CRT aufgerufen.
- Die CRT wird nur gelinkt, nicht reinkompiliert. Die reingelinkte CRT hatte wahrscheinlich Exceptions eingeschaltet und nutzt irgendwo was mit Locales (Fehlermeldungen?).
- Visual C++ hievt den Scheiß also auch bei mir rein
- Sicher liegen die main() für DLL und EXE in der selben CPP, also werden beide gelinkt, also rutscht das Kommandozeilenzeug mit rein.
Warum dann nicht einfach einen eigenen Einsprungspunkt anlegen?
Weil dann alles aufhört, zu funktionieren. Ich bin so weit gekommen, dass die dynamisch gebundene Version läuft – aber die statisch gebundene stürzt in irgendeinem globalen Initializer ab weil da ein Lock genommen wird, der auf globale, thread-lokale CRT-Datenstrukturen zugreifen will oder so. Keine Ahnung; hab' seit 'nem Jahr nicht mehr reingeguckt weil ich dachte, es könnte ja so schlimm nicht sein … ich Narr
Re: Jammer-Thread
Verfasst: 29.04.2016, 20:33
von Krishty
Seit Update 2 unterstützt Visual C++’ STL kein
/RTCc mehr. Das ist die Compiler-Option, die bei
int x = …;
short y = short(x);
zur Laufzeit prüft, ob bei der Konvertierung Daten verloren gehen. Äußerst nützlich, um Integer Overflow Attacks zu finden und Fixed-Point-Arithmetik zu debuggen … und jetzt quasi nicht mehr brauchbar (außer, man fügt obskure
#defines hinzu, um drumherum zu bauen).
Ich nutze die STL nur noch in Assimp und anderen Drittprojekten, aber trotzdem … was für eine Scheiße.
Nachtrag: Und
hid.lib haben sie auch noch entfernt oder verschoben. Jedenfalls für 32-Bit-Programme. Jetzt kann ich keine Joysticks mehr ansteuern … aber x64 linkt noch immer problemlos … WTF
Nachtrag 2: Sie haben mein x86-Projekt auf das Windows 10-SDK hochgepatcht, und das enthält keine
hid.lib. Die x64-Version kompiliert noch mit dem Windows 7-/8-/8.1-SDK, und die enthalten jeweils
hid.lib. WTF WTF was soll das; erst eine Bibliothek aus dem SDK löschen und dann bei Visual C++-Patches die Bibliothekspfade auf andere SDKs ändern, aber nur bei der Hälfte der Konfigurationen?! Da kann ich ja bald auf CMake umsteigen …
Nachtrag 3: Es ist der Windows-XP-Kompatitibilitätsmodus, der kaputtgegangen ist. Stelle ich auf Vista oder höher um, findet er die Bibliothek. Warum
Nachtrag 4: Oh lol. Diversen Usern geht mit Update 2 CTP der XP-Modus kaputt (siehe Kommentare
hier). Sie eröffnen ein Ticket
hier. Dann wird ein Workaround hochgeladen, aber irgendwie ist das Ticketsystem kaputt und niemand kann ihn sehen. Irgendwann stellen sie ihn dann als ZIP-Download zur Verfügung. Die ZIP besteht aus einer Sammlung von Property Sheets für MSBuild. Soll ich meine Props jetzt durch die Dateien in der ZIP ersetzen? Und jedem meiner User sagen, sie müssen das selbe machen, um das Programm kompilierbar zu kriegen? Hmmm …
Re: Jammer-Thread
Verfasst: 04.05.2016, 13:26
von Jonathan
Ich habe aus Testzwecken einen Ordner in
#.git umbenannt. Jetzt wollte ich ihn wieder
.git nennen, aber der Explorer sagt dazu nur "You must type a filename". Die
Lösung ist, den Ordner
.git. zu nennen, dann 'denkt' Windows, es sei ein Dateiname mit leerer Endung, anstatt ein leerer Dateiname mit Endung. Oh un der Punkt am Ende wird 'praktischerweise' automatisch entfernt. Ist jetzt nicht wirklich irgendwie schlimm, aber doch durchaus kurios.