Visual C++-CRT ersetzen
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Visual C++-CRT ersetzen
Es gibt im Netz viel zu wenig Infos dazu, also steuere ich mal alles bei, was mir so bei /NODEFAULTLIB (ohne Microsoft-CRT kompilieren) begegnet.
1. Alle CRT-Ersatzfunktionen müssen in eine eigene .cpp ohne globale Optimierungen. Nicht aus kosmetischen Gründen, sondern weil viele CRT-Funktionen als Intrinsics realisiert sind:
MyStruct x = { 0 };
ersetzt Visual C++ durch
MyStruct x;
memset(&x, 0, sizeof(x));
und der Optimizer optimiert bei kleinen structs den Funktionsaufruf weg und nutzt stattdessen direkt ein Nullregister oder so. Sowas ist nur möglich, wenn der Compiler das Verhalten einer Funktion fest eingebaut hat, und das passiert bei CRT-Funktionen oft. Wenn solche Intrinsics ersetzt werden sollen, bringt das den Optimizer durcheinander, darum kann man sie nur in einer gesonderten .cpp ohne globale Optimierung ersetzen und hat keinen Einfluss auf die Aufrufe, die geinlinet oder wegoptimiert werden.
2. new löst, selbst als Placement new, eine Referenz zu delete und type_info aus.
Sogar, wenn Exceptions und Run-Time Type Information deaktiviert sind (was mit Placement new legitimer Anwendungsfall ist). Darum muss man immer einen eigenen
void __cdecl operator delete(void *, size_t)
zur Verfügung stellen, den man halt leer macht oder so. Fragt mich bitte nicht, wo der zweite Parameter herkommt. Das weiß wohl nur Microsofts Compiler-Team. Ebenso müsst ihr
class type_info {
~type_info() { }
};
zur Verfügung stellen, weil new aus irgendeinem Grund die Virtual Function Table von type_info braucht und die nunmal aus dem Destruktor besteht. Beachtet, dass die obige Version Speicher verliert, falls ihr type_info tatsächlich nutzt und auf Namen, Hash, o.ä. zugreift. In dem Fall müsst ihr einen vollwertigen Destruktor gemäß der Dokumentation irgendwo auf einer Kaffee-bekleckerten, vollgekritzelten College-Block-Rückseite aus der MSDN entwickeln. Im Debugger *irgendeines* Visual-C++-Projekts
(type_info*)0
eingeben stellt euch ebenfalls das Layout zur Verfügung.
3. Dieses delete und type_info müssen in der selben .cpp definiert sein, in der ihr auch euer new definiert ist.
… oder alternativ in jeder .cpp, in der new vorkommt. Ihr erkennt das Muster dahinter, den Master Plan des Compilerbaus! … oder? Sonst kriegt ihr so schöne Meldungen wie
error LNK2016: absolute symbol '@comp.id' used as target of REL32 relocation in section 8D
oder
fatal error C1001: An internal error has occurred in the compiler.
4. Ihr dürft Run-Time Type nur deaktivieren, wenn type_info in der selben Datei wie new definiert ist.
Denn sonst werden eure Definitionen einfach ignoriert und es gibt
error LNK2001: unresolved external symbol "const type_info::`vftable'"
Fragt nicht.
Mehr trage ich nach, wenn mir gerade danach ist.
1. Alle CRT-Ersatzfunktionen müssen in eine eigene .cpp ohne globale Optimierungen. Nicht aus kosmetischen Gründen, sondern weil viele CRT-Funktionen als Intrinsics realisiert sind:
MyStruct x = { 0 };
ersetzt Visual C++ durch
MyStruct x;
memset(&x, 0, sizeof(x));
und der Optimizer optimiert bei kleinen structs den Funktionsaufruf weg und nutzt stattdessen direkt ein Nullregister oder so. Sowas ist nur möglich, wenn der Compiler das Verhalten einer Funktion fest eingebaut hat, und das passiert bei CRT-Funktionen oft. Wenn solche Intrinsics ersetzt werden sollen, bringt das den Optimizer durcheinander, darum kann man sie nur in einer gesonderten .cpp ohne globale Optimierung ersetzen und hat keinen Einfluss auf die Aufrufe, die geinlinet oder wegoptimiert werden.
2. new löst, selbst als Placement new, eine Referenz zu delete und type_info aus.
Sogar, wenn Exceptions und Run-Time Type Information deaktiviert sind (was mit Placement new legitimer Anwendungsfall ist). Darum muss man immer einen eigenen
void __cdecl operator delete(void *, size_t)
zur Verfügung stellen, den man halt leer macht oder so. Fragt mich bitte nicht, wo der zweite Parameter herkommt. Das weiß wohl nur Microsofts Compiler-Team. Ebenso müsst ihr
class type_info {
~type_info() { }
};
zur Verfügung stellen, weil new aus irgendeinem Grund die Virtual Function Table von type_info braucht und die nunmal aus dem Destruktor besteht. Beachtet, dass die obige Version Speicher verliert, falls ihr type_info tatsächlich nutzt und auf Namen, Hash, o.ä. zugreift. In dem Fall müsst ihr einen vollwertigen Destruktor gemäß der Dokumentation irgendwo auf einer Kaffee-bekleckerten, vollgekritzelten College-Block-Rückseite aus der MSDN entwickeln. Im Debugger *irgendeines* Visual-C++-Projekts
(type_info*)0
eingeben stellt euch ebenfalls das Layout zur Verfügung.
3. Dieses delete und type_info müssen in der selben .cpp definiert sein, in der ihr auch euer new definiert ist.
… oder alternativ in jeder .cpp, in der new vorkommt. Ihr erkennt das Muster dahinter, den Master Plan des Compilerbaus! … oder? Sonst kriegt ihr so schöne Meldungen wie
error LNK2016: absolute symbol '@comp.id' used as target of REL32 relocation in section 8D
oder
fatal error C1001: An internal error has occurred in the compiler.
4. Ihr dürft Run-Time Type nur deaktivieren, wenn type_info in der selben Datei wie new definiert ist.
Denn sonst werden eure Definitionen einfach ignoriert und es gibt
error LNK2001: unresolved external symbol "const type_info::`vftable'"
Fragt nicht.
Mehr trage ich nach, wenn mir gerade danach ist.
- xq
- Establishment
- Beiträge: 1590
- Registriert: 07.10.2012, 14:56
- Alter Benutzername: MasterQ32
- Echter Name: Felix Queißner
- Wohnort: Stuttgart & Region
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
Bäh klingt das nervig. Ich bin grade echt froh, hauptsächlich GCC oder clang zu verwenden...
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…
Programmiert viel in Zig und nervt Leute damit.
Programmiert viel in Zig und nervt Leute damit.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
Hast du denn mal einen Dump gemacht, wie viel von libc in deinen Programmen landet?
Re: Visual C++-CRT ersetzen
Statisch kompiliertes Hello World in C ist mit gcc über 1MB groß… glibc lässt grüßen.
- xq
- Establishment
- Beiträge: 1590
- Registriert: 07.10.2012, 14:56
- Alter Benutzername: MasterQ32
- Echter Name: Felix Queißner
- Wohnort: Stuttgart & Region
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
Krishty hat geschrieben:Hast du denn mal einen Dump gemacht, wie viel von libc in deinen Programmen landet?
Mir ging es eher um das Gefrickel mit den libcs, ich schreib grade an einem Kernel und muss damit auch meine libc selbst implementieren, habe aber bei weitem weniger Probleme damit als Krishty.Biolunar hat geschrieben:Statisch kompiliertes Hello World in C ist mit gcc über 1MB groß… glibc lässt grüßen.
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…
Programmiert viel in Zig und nervt Leute damit.
Programmiert viel in Zig und nervt Leute damit.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
Ah, okok. Ich war auch über die libc-Implementierung von Stack Probes gestolpert, und die ist, IIRC, tatsächlich einfacher. Microsofts _chkstk() arbeitet mit den Voraussetzungen
- keinen Stapelspeicher reservieren (alles nur in Registern machen)
- nur die Register rax, r10, r11 nutzen
- es muss im Fall eines Stack Overflows während _alloca() sauberes Unwinding ermöglichen
- es wird während des Funktionsprologs aufgerufen, es würde also keine gültige Kette von Stack Frames mehr existieren, sobald die Funktion an Stack oder aktiven Registern rumfummeln würde
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
Schon länger ein besonderes Sorgenkind ist für mich float-zu-String, also gcvt(), fcvt(), ftoa(), usw.
Ich habe mich jahrelang gesträubt, dtoa.c in meinen Code aufzunehmen, obwohl es der seit 30 Jahren auf Herz und Nieren getestete de-facto-Code ist, der in jedem Betriebssystem und jedem Compiler und jeder Runtime steckt, von PHP über Java bis C:
Exploring Binary: PHP Hangs On Numeric Value 2.2250738585072011e-308
Exploring Binary: Java Hangs When Converting 2.2250738585072012e-308
Zum einen habe ich es nicht selbst verfasst und würde dafür sicher auch Jahre brauchen; zum anderen ist es einfach gigantisch viel Code:
Stack Overflow: Why does “dtoa.c” contain so much code?
(Kurz: Weil es verflucht schwer ist, 2^64 Werte samt Denormalisierungen in eine andere Basis umzurechnen, wenn keine Variable, mit der man rechnet, mehr als 2^64 Werte speichern kann, und das dann auf jeder Architektur der Welt zum Laufen zu kriegen.)
Das sind für mich verdammt viele Gründe, lieber auf was zurückzugreifen, das eh schon in meinem Adressraum rumliegt … also habe ich angefangen, im Windows-Kernel nach Ersatz zu suchen. Ich bin ziemlich schnell fündig geworden:
User32.dll exportiert einen sprintf()-Klon!
Der ist zwar nur auf 1024 Zeichen limitiert, und hoffnungslos veraltet, aber für
char buffer[349]; // längste mögliche Repräsentation einer double
wsprintf(buffer, "%g", value);
wird es jawohl noch reichen, oder?
Nein.
Denn die Funktion ist so alt, dass sie keine Gleitkommazahlen unterstützt. Man kann nur Integer und Zeiger formatieren.
Jetzt suche ich weiter. Die Shell zeigt ja z.B. in Dateieigenschaften Gleitkommazahlen an; irgendwo muss Windows Konvertierungs-Code geladen haben …
Warum nicht einfach die CRT-DLL laden und mit GetProcAddress(crt, "_gcvt") reingreifen, fragt ihr? Sobald die CRT-DLL geladen wird, lädt automatisch auch der ganze Müll, den ich gerade erst aus meinen Programmen rausgeschmissen habe. Etliche Megabytes ANSI-zu-Unicode-Locale-Tabellen zum Beispiel. Und selbst wenn das dann geladen ist, stürzt die CRT gern mal ab, weil Thread-local Storage usw. nicht initialisiert wird, wenn man sie nachträglich lädt. (Den Code fügt der Compiler ja in den Einsprungspunkt der Programme ein, wenn man linkt.)
Ich habe mich jahrelang gesträubt, dtoa.c in meinen Code aufzunehmen, obwohl es der seit 30 Jahren auf Herz und Nieren getestete de-facto-Code ist, der in jedem Betriebssystem und jedem Compiler und jeder Runtime steckt, von PHP über Java bis C:
Exploring Binary: PHP Hangs On Numeric Value 2.2250738585072011e-308
Exploring Binary: Java Hangs When Converting 2.2250738585072012e-308
Zum einen habe ich es nicht selbst verfasst und würde dafür sicher auch Jahre brauchen; zum anderen ist es einfach gigantisch viel Code:
Stack Overflow: Why does “dtoa.c” contain so much code?
(Kurz: Weil es verflucht schwer ist, 2^64 Werte samt Denormalisierungen in eine andere Basis umzurechnen, wenn keine Variable, mit der man rechnet, mehr als 2^64 Werte speichern kann, und das dann auf jeder Architektur der Welt zum Laufen zu kriegen.)
Das sind für mich verdammt viele Gründe, lieber auf was zurückzugreifen, das eh schon in meinem Adressraum rumliegt … also habe ich angefangen, im Windows-Kernel nach Ersatz zu suchen. Ich bin ziemlich schnell fündig geworden:
User32.dll exportiert einen sprintf()-Klon!
Der ist zwar nur auf 1024 Zeichen limitiert, und hoffnungslos veraltet, aber für
char buffer[349]; // längste mögliche Repräsentation einer double
wsprintf(buffer, "%g", value);
wird es jawohl noch reichen, oder?
Nein.
Denn die Funktion ist so alt, dass sie keine Gleitkommazahlen unterstützt. Man kann nur Integer und Zeiger formatieren.
Jetzt suche ich weiter. Die Shell zeigt ja z.B. in Dateieigenschaften Gleitkommazahlen an; irgendwo muss Windows Konvertierungs-Code geladen haben …
Warum nicht einfach die CRT-DLL laden und mit GetProcAddress(crt, "_gcvt") reingreifen, fragt ihr? Sobald die CRT-DLL geladen wird, lädt automatisch auch der ganze Müll, den ich gerade erst aus meinen Programmen rausgeschmissen habe. Etliche Megabytes ANSI-zu-Unicode-Locale-Tabellen zum Beispiel. Und selbst wenn das dann geladen ist, stürzt die CRT gern mal ab, weil Thread-local Storage usw. nicht initialisiert wird, wenn man sie nachträglich lädt. (Den Code fügt der Compiler ja in den Einsprungspunkt der Programme ein, wenn man linkt.)
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
dtoa.c nutzt memcpy(), und das hat im Compiler eine ganz besondere Stellung.
Will man memcpy() ersetzen, kann man dafür nicht einfach eine Definition schreiben. Neeeeiiiiin. Denn: memcpy() ist ein Intrinsic, und Intrinsics kann man nicht überschreiben!
error C2169: 'memcpy': intrinsic function, cannot be defined
Aber dafür gibt es ein wenig genutztes #pragma:
#pragma function(memcpy)
Das teilt dem Compiler mit, dass er memcpy() ab jetzt wie eine normale Funktion zu behandeln hat, und wir können es dann definieren. Zunächst erhalten wir jedoch:
warning C4164: 'memcpy': intrinsic function not declared
Das ist zwar nur eine Warnung, sorgt aber dafür, dass die Definition nicht anerkannt wird. Also deklarieren wir memcpy() und erhalten:
extern "C" {
void * __cdecl memcpy(void *, void const *, size_t); // Deklaration aus formalen Gründen
# pragma function(memcpy) // nicht als Intrinsic behandeln
void * __cdecl memcpy(void * d, void const * s, size_t n) { // tatsächliche Definition
__movsb(d, s, n); // seit ein, zwei CPU-Generationen die schnellste Art, Daten zu kopieren
return d;
}
}
Wunderschön! memmove() ist einfacher: Definition hinklatschen und gut ist.
Will man memcpy() ersetzen, kann man dafür nicht einfach eine Definition schreiben. Neeeeiiiiin. Denn: memcpy() ist ein Intrinsic, und Intrinsics kann man nicht überschreiben!
error C2169: 'memcpy': intrinsic function, cannot be defined
Aber dafür gibt es ein wenig genutztes #pragma:
#pragma function(memcpy)
Das teilt dem Compiler mit, dass er memcpy() ab jetzt wie eine normale Funktion zu behandeln hat, und wir können es dann definieren. Zunächst erhalten wir jedoch:
warning C4164: 'memcpy': intrinsic function not declared
Das ist zwar nur eine Warnung, sorgt aber dafür, dass die Definition nicht anerkannt wird. Also deklarieren wir memcpy() und erhalten:
extern "C" {
void * __cdecl memcpy(void *, void const *, size_t); // Deklaration aus formalen Gründen
# pragma function(memcpy) // nicht als Intrinsic behandeln
void * __cdecl memcpy(void * d, void const * s, size_t n) { // tatsächliche Definition
__movsb(d, s, n); // seit ein, zwei CPU-Generationen die schnellste Art, Daten zu kopieren
return d;
}
}
Wunderschön! memmove() ist einfacher: Definition hinklatschen und gut ist.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
Natürlich merke ich erst jetzt, wo ich schon auf dtoa.c umgestiegen bin, dass es doch ein sprintf() im Windows-Kernel gibt: Und zwar direkt in ntdll.dll. Da ist es auch schon seit NT 3.51. Wie der gesamte Rest der CRT ebenfalls.
Ich bin eher zufällig drauf gestoßen, als ich diese ReactOS-News las.
Ist auch kein großes Ding, denn dieses sprintf() findet sich nicht in der offiziellen ntdll.lib, die man mit Visual Studio einbindet. Man müsste also entweder eine eigene Importbibliothek schreiben (Wartungsalptraum) oder die Funktion erst zur Laufzeit suchen (hässlich). Vielleicht bleibe ich dann doch lieber bei dtoa.c, da habe ich letztendlich die volle Kontrolle über das, was passiert.
Ich bin eher zufällig drauf gestoßen, als ich diese ReactOS-News las.
Ist auch kein großes Ding, denn dieses sprintf() findet sich nicht in der offiziellen ntdll.lib, die man mit Visual Studio einbindet. Man müsste also entweder eine eigene Importbibliothek schreiben (Wartungsalptraum) oder die Funktion erst zur Laufzeit suchen (hässlich). Vielleicht bleibe ich dann doch lieber bei dtoa.c, da habe ich letztendlich die volle Kontrolle über das, was passiert.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
Umgestiegen auf Visual C++ 2017.
Mein x86-64-Code läuft problemlos – da gab es tatsächlich keine Breaking Changes.
Die x86-32-Version hat ein Problem:
LIBCMT.lib(_ftol3_.obj) : error LNK2019: unresolved external symbol __except1 referenced in function __ftol3_except
Wenn man auf x86-32 double zu long castet, ruft Visual C++ die CRT-Funktion _ftol3_except() auf (ob die Konvertierung in Hardware oder Software durchgeführt werden kann, hängt von FPU-Nutzung, SSE-Verfügbarkeit und Exception-Einstellungen ab). Die führt die Konvertierung durch und ruft nötigenfalls _except1() auf (mit einem Unterstrich wegen C Calling Convention), um Exceptions à la NaN/Overflow/etc. zu schmeißen, falls FPU-Exceptions eingeschaltet sind (jedenfalls entnehme ich das der Wine-Kopie hier).
Das Ding ist: Visual C++ schluckt mein _except1() nicht. Ich habe keine Ahnung, woran’s liegt. Ich habe jetzt alle Calling Conventions und Parameterkombinationen durch, und es will einfach nicht gefunden werden. Fuck.
Ich nutze keine FPU-Exceptions, und unter Visual C++ 2015 hat’s noch funktioniert … ärgerlich :(
Nachtrag: Die Funktion muss in einer Übersetzungseinheit liegen, die ohne globale Optimierungen kompiliert wird. Bei allen anderen Intrinsics kommt eine entsprechende Fehlermeldung, nur bei _except1() nicht. Wahrscheinlich haben sie es nicht in die Compiler-interne Liste eingetragen. Jetzt ist jedenfalls alles bestens portiert.
// Raises floating-point exceptions. Called after floating-point operations are emulated in software (e.g.
// “double”-to-“long long“-conversion, which is not natively supported on 32-bit x86).
double _except1(UInt4B, int, double, double result, UInt4B, void *) {
return result;
}
Mein x86-64-Code läuft problemlos – da gab es tatsächlich keine Breaking Changes.
Die x86-32-Version hat ein Problem:
LIBCMT.lib(_ftol3_.obj) : error LNK2019: unresolved external symbol __except1 referenced in function __ftol3_except
Wenn man auf x86-32 double zu long castet, ruft Visual C++ die CRT-Funktion _ftol3_except() auf (ob die Konvertierung in Hardware oder Software durchgeführt werden kann, hängt von FPU-Nutzung, SSE-Verfügbarkeit und Exception-Einstellungen ab). Die führt die Konvertierung durch und ruft nötigenfalls _except1() auf (mit einem Unterstrich wegen C Calling Convention), um Exceptions à la NaN/Overflow/etc. zu schmeißen, falls FPU-Exceptions eingeschaltet sind (jedenfalls entnehme ich das der Wine-Kopie hier).
Das Ding ist: Visual C++ schluckt mein _except1() nicht. Ich habe keine Ahnung, woran’s liegt. Ich habe jetzt alle Calling Conventions und Parameterkombinationen durch, und es will einfach nicht gefunden werden. Fuck.
Ich nutze keine FPU-Exceptions, und unter Visual C++ 2015 hat’s noch funktioniert … ärgerlich :(
Nachtrag: Die Funktion muss in einer Übersetzungseinheit liegen, die ohne globale Optimierungen kompiliert wird. Bei allen anderen Intrinsics kommt eine entsprechende Fehlermeldung, nur bei _except1() nicht. Wahrscheinlich haben sie es nicht in die Compiler-interne Liste eingetragen. Jetzt ist jedenfalls alles bestens portiert.
// Raises floating-point exceptions. Called after floating-point operations are emulated in software (e.g.
// “double”-to-“long long“-conversion, which is not natively supported on 32-bit x86).
double _except1(UInt4B, int, double, double result, UInt4B, void *) {
return result;
}
Zuletzt geändert von Krishty am 09.09.2018, 03:39, insgesamt 1-mal geändert.
-
- Beiträge: 32
- Registriert: 29.07.2002, 11:43
Re: Visual C++-CRT ersetzen
Früher in Visualstudio hatte ich etwas wie LIBCTINY.LIB oder so. Gibt es das eigentlich gar nicht mehr? Kleine Demonstrationsprogramme waren damit locker nur 8kb groß, selbst mit ein paar Bitmaps in den Ressourcen.
Ich habe vor ein paar Tagen mal gegoogled und dort die minicrt.lib gefunden, die es vor 7 Jahren wohl noch gab.
Mein Beweggrund waren die kleinen Dateigrößen und die MiniCRT hatt einen vor allen eigenartigen Dingen bewahrt. Man konnte einiges vielleicht nicht nutzen, aber solange man sehr einfachen Code geschrieben hat, ist auch nichts passiert. Wobei ich mir jetzt gar nicht sicher bin, ob die STL funktioniert hat. Der Heap hat nicht funktioniert.
Warum programmierst du ohne Standard Libraries?
Ich habe vor ein paar Tagen mal gegoogled und dort die minicrt.lib gefunden, die es vor 7 Jahren wohl noch gab.
Mein Beweggrund waren die kleinen Dateigrößen und die MiniCRT hatt einen vor allen eigenartigen Dingen bewahrt. Man konnte einiges vielleicht nicht nutzen, aber solange man sehr einfachen Code geschrieben hat, ist auch nichts passiert. Wobei ich mir jetzt gar nicht sicher bin, ob die STL funktioniert hat. Der Heap hat nicht funktioniert.
Warum programmierst du ohne Standard Libraries?
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
Sowas gibt es immernoch, aber Microsoft verändert die CRT von Release zu Release:
Was Verzicht auf Standardbibliotheken angeht:
- früher hat der Compiler die FPU für float-zu-int-Konvertierung genutzt; seit einigen Jahren braucht er dafür eine SSE-kompatible Funktion aus der CRT
- früher gab es keinen Security Check (/GS), heute muss die CRT alle beteiligten Funktionen liefern
- früher hat Visual Studio kein long long unterstützt, heute emuliert es 64-Bit-Arithmetik auf 32-Bit-Systemen mit der CRT
- seit 2015 nutzt Visual C++ die Universal CRT aus Windows statt eine eigene mitzubringen
Was Verzicht auf Standardbibliotheken angeht:
- ich will keine Abhängigkeiten
- ich nutze keine Ausnahmebehandlung, aber dann darf man die STL nicht mehr benutzen
- ich habe meine eigenen OS-Wrapper
- weniger Bloat
- Kompilierzeit (meine Projekte kompilieren größtenteils in unter einer Sekunde; mit STL verzehnfacht sich das locker)
-
- Beiträge: 32
- Registriert: 29.07.2002, 11:43
Re: Visual C++-CRT ersetzen
Genau das war der Grund. Ich wollte wieder etwas auf <20kb bringen, habe versucht das alte Projekt zu übersetzen und es hat nicht funktioniert.Krishty hat geschrieben: Alte Projekte wie Libctiny und minicrt werden deshalb unbrauchbar, wenn man sie nicht für jedes Visual C++-Release neu anpasst.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Visual C++-CRT ersetzen
Bei Handmade Hero gibt es einen ähnlichen Thread, der meinen um einiges ergänzt – z. B. mit Links zu funktionierenden Assembler-Versionen der fehlenden 64-Bit-Arithmetik in 32-Bit-Builds. Aber genießt ihn mit Vorsicht; es steht auch viel Halbwissen drin.