(erledigt) [C++] Array Funktionszeiger Compile-Time-konstant
- Krishty
- Establishment
- Beiträge: 8268
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
(erledigt) [C++] Array Funktionszeiger Compile-Time-konstant
Hi,
Gibt es zufällig eine Möglichkeit, ein Array von Funktionszeigern schon zur Compile-Time zu initialisieren?
Selbst, wenn nicht (afaik sind Win32-PEs ja kein position-independent code?) – der Compiler (VS 2010) sorgt dafür, dass die Laufzeitinitialisierung des Arrays als endlose Liste von movs geschieht. Könnte ich ihn zumindest dazu kriegen, dafür SSE zu benutzen?
Gruß, Ky
Edit: Kurzfassung: Compiler-Bug; wird in nächster Zeit nicht behoben, möglichst das & weglassen.
Gibt es zufällig eine Möglichkeit, ein Array von Funktionszeigern schon zur Compile-Time zu initialisieren?
Selbst, wenn nicht (afaik sind Win32-PEs ja kein position-independent code?) – der Compiler (VS 2010) sorgt dafür, dass die Laufzeitinitialisierung des Arrays als endlose Liste von movs geschieht. Könnte ich ihn zumindest dazu kriegen, dafür SSE zu benutzen?
Gruß, Ky
Edit: Kurzfassung: Compiler-Bug; wird in nächster Zeit nicht behoben, möglichst das & weglassen.
Zuletzt geändert von Krishty am 22.06.2010, 21:55, insgesamt 1-mal geändert.
-
- Beiträge: 91
- Registriert: 07.12.2009, 16:42
- Echter Name: Fabian R
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Das sollte vlt. mit constexpr aus C++0x gehen. Wird aber imho noch nicht von VS 2010 unterstützt.
- Krishty
- Establishment
- Beiträge: 8268
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Das ging schnell :)
Ich glaube nicht, dass constexpr einen Unterschied machen wird – das Array ist static const deklariert, er würde also garnicht erst kompilieren, wenn in der Initialisierung keine Compile-Time constant expression stünde. Auch sind Funktionszeiger keine Daten, die von Anfang an feststehen, sondern erst zu Laufzeit. Der Compiler kennt während des Linkvorgangs erst die Offsets der Funktionen von der Basisadresse des Moduls, die sich beim Laden möglicherweise noch ändern, wenn die bevorzugte Basisadresse schon belegt ist.
Die Frage ist also eher, wie ich den Compiler dazu kriege, dieses Array als für die Relocation-Table der Exe gedacht zu erkennen.
Meine Kenntnisse um die PE-Internals und alles außerhalb der main() sind leider nicht sehr tiefgreifend – darum ist alles, was ich hier schreibe, ins Blaue geraten und vielleicht komplett falsch.
Ich glaube nicht, dass constexpr einen Unterschied machen wird – das Array ist static const deklariert, er würde also garnicht erst kompilieren, wenn in der Initialisierung keine Compile-Time constant expression stünde. Auch sind Funktionszeiger keine Daten, die von Anfang an feststehen, sondern erst zu Laufzeit. Der Compiler kennt während des Linkvorgangs erst die Offsets der Funktionen von der Basisadresse des Moduls, die sich beim Laden möglicherweise noch ändern, wenn die bevorzugte Basisadresse schon belegt ist.
Die Frage ist also eher, wie ich den Compiler dazu kriege, dieses Array als für die Relocation-Table der Exe gedacht zu erkennen.
Meine Kenntnisse um die PE-Internals und alles außerhalb der main() sind leider nicht sehr tiefgreifend – darum ist alles, was ich hier schreibe, ins Blaue geraten und vielleicht komplett falsch.
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Ja, relocatable (mit den bekannten Vor– und Nachteilen im Vergleich zu Linux’ ELF). Die /FIXED–Option fuer den Linker hast du probiert?afaik sind Win32-PEs ja kein position-independent code?
- Krishty
- Establishment
- Beiträge: 8268
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Keine Veränderung außer, dass er andere Register benutzt, um die Ziele der movs anzugeben :/
Achja, lohnt sich eigentlich /DYNAMICBASE, d.h. erschwert das die Entwicklung von Trainern und Cheat-Tools?
Achja, lohnt sich eigentlich /DYNAMICBASE, d.h. erschwert das die Entwicklung von Trainern und Cheat-Tools?
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Die Startup–Zeit verschlechtert sich wegen dem Rebasing, Cheater abhalten kannst du sowieso nicht. /DYNAMICBASE ist als Sicherheitsfeature gedacht – eingeschleuster Code ist ja oftmals winzig, das Ermitteln der korrekten Basisadresse ist alse ein Showstopper. Ein Cheat, Crack oder Trainer hingegen ist ja meist ein vollwertiges Programm, wird also dadurch nicht aufgehalten.
- Krishty
- Establishment
- Beiträge: 8268
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Naja, zumindest Trainer sind meist extern und dürften mit dem Manipulieren des Prozessspeichers bedeutende Probleme haben sobald sie nicht mehr wissen, wo der Stack anfängt. Aber sei’s drum, mit der .reloc-Section wären wieder 20 KiB weg.
Das ursprüngliche Problem bleibt aber bestehen. Ich finde haufenweise Threads aus dem Embedded-Programming-Bereich, wo gefragt wird, wie Arrays von Funktionszeigern im ROM statt RAM landen … überall funktioniert es, sobald const oder static const dran stehen. Bei mir mit Win32 aber nicht. Ich werde gleich mal eine kleine Testanwendung bauen um zu sehen, ob es an mir oder an dem Compiler liegt … habe keine Lust, schon wieder einen Bug zu melden.
Das ursprüngliche Problem bleibt aber bestehen. Ich finde haufenweise Threads aus dem Embedded-Programming-Bereich, wo gefragt wird, wie Arrays von Funktionszeigern im ROM statt RAM landen … überall funktioniert es, sobald const oder static const dran stehen. Bei mir mit Win32 aber nicht. Ich werde gleich mal eine kleine Testanwendung bauen um zu sehen, ob es an mir oder an dem Compiler liegt … habe keine Lust, schon wieder einen Bug zu melden.
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Der Stack ist von Dynamic Basing nicht betroffen, denke ich. Nur die Stelle, an der das Betriebsystem PE–Images in den Adressraum hineinmap’d.
- Krishty
- Establishment
- Beiträge: 8268
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Laut Wikipedia schon. Naja, sonst wäre das Ganze auch ziemlich wenig effektiv.
Bei einem Miniprojekt optimiert er das Erzeugen des Tables übrigens weg. Ich muss also mal genauer nachbohren ob nun Templates, Multi-Dimensionality des Arrays, seine pure Länge oder meine Dummheit verantwortlich sind.
Bei einem Miniprojekt optimiert er das Erzeugen des Tables übrigens weg. Ich muss also mal genauer nachbohren ob nun Templates, Multi-Dimensionality des Arrays, seine pure Länge oder meine Dummheit verantwortlich sind.
Zuletzt geändert von Krishty am 06.06.2010, 21:30, insgesamt 1-mal geändert.
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Ah, ok. Laut http://msdn.microsoft.com/en-us/magazine/cc337897.aspx auch. Mein Fehler.
- Krishty
- Establishment
- Beiträge: 8268
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Okay, habe es: Wird das Array so initialisiert, landet für jedes Element ein mov in der Exe. Wird das Array so initialisiert, landet alles in der Read-only-Section und es entsteht kein Run-Time-Overhead.
Ist eines von beiden vielleicht eine Microsoft-Extension? Ist es legal, Funktionsadressen mit & abzufragen? Macht das einen Unterschied (funktionell scheint das gleiche zu passieren)? Ich finde im Netz auf die Schnelle nur die Variante ohne & …
Wahnsinn, das & hat mich 7 KiB .text und 3 KiB .data gekostet. Das war die Optimierung mit dem größten Ursache-Wirkung-Verhältnis meiner bisherigen Programmierlaufbahn.
Code: Alles auswählen
static void (* const Functions[])() = { &FuncA, &FuncB };
Code: Alles auswählen
static void (* const Functions[])() = { FuncA, FuncB };
Ist eines von beiden vielleicht eine Microsoft-Extension? Ist es legal, Funktionsadressen mit & abzufragen? Macht das einen Unterschied (funktionell scheint das gleiche zu passieren)? Ich finde im Netz auf die Schnelle nur die Variante ohne & …
Wahnsinn, das & hat mich 7 KiB .text und 3 KiB .data gekostet. Das war die Optimierung mit dem größten Ursache-Wirkung-Verhältnis meiner bisherigen Programmierlaufbahn.
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Ich mag mich schon wieder irren, aber ich glaube, ‘&’ auf eine Funktion angewandt liefert einen Pointer auf sie, einfach nur der Funktionsname eine Referenz.Ist es legal, Funktionsadressen mit & abzufragen?
- Krishty
- Establishment
- Beiträge: 8268
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Ja, ich mag dir auch nicht aufbürden, dich für Details einer so missgeborenen Syntax durch den Standard zu wühlen. Hier wird gesagt, dass das Weglassen des & nicht portabel sei. Sollte das zutreffen, geht morgen mein Bug-Report raus.
- Krishty
- Establishment
- Beiträge: 8268
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Sooooooo.
Mal die Ergebnisse meiner Recherche:
• & kann man benutzen, muss man aber nicht. Da man Funktionen nur für zwei Dinge benutzen kann (zum Aufrufen oder zum Abholen der Adresse) wird im nicht-Aufruf-Fall implizit zum Funktionszeiger gecastet.
• Das Array wird nur dann zur Laufzeit initialisiert, wenn die Funktionen, deren Adressen man nimmt, Templates sind. Mit C-Funktionen funktioniert es immer korrekt, egal, ob ein & vor der Funktion hängt oder nicht.
Darum gehe ich davon aus, dass das ein Bug ist und habe einen entsprechenden Report mit kurzem, einprägsamem Titel abgeschickt. Wen es interessiert und/oder wer ihn reproduzieren kann, ist zum Voten eingeladen.
Mal die Ergebnisse meiner Recherche:
• & kann man benutzen, muss man aber nicht. Da man Funktionen nur für zwei Dinge benutzen kann (zum Aufrufen oder zum Abholen der Adresse) wird im nicht-Aufruf-Fall implizit zum Funktionszeiger gecastet.
• Das Array wird nur dann zur Laufzeit initialisiert, wenn die Funktionen, deren Adressen man nimmt, Templates sind. Mit C-Funktionen funktioniert es immer korrekt, egal, ob ein & vor der Funktion hängt oder nicht.
Darum gehe ich davon aus, dass das ein Bug ist und habe einen entsprechenden Report mit kurzem, einprägsamem Titel abgeschickt. Wen es interessiert und/oder wer ihn reproduzieren kann, ist zum Voten eingeladen.
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Zu 1.: das entspraeche meinem Verstaendnis des Sprachstandards:
- Der Funktionsname alleine ist eine Referenz, d.h.
Code: Alles auswählen
void foo(int); void bar(int); void (&foo_ptr)(int) = foo; foo_ptr(4); // OK foo_ptr = bar; // ERROR, reference cannot be reassigned
- Ebenso, der Funktionsname wird implizit nach T* (wobei T der function-type ist) konvertiert. Das gilt iirc nur fuer ‘normale’ Funktionen, Memberfunktionen unterstuetzen diese Konversion nicht, d.h.
Code: Alles auswählen
class MyClass { void foo(int) const; }; void (MyClass::*myptr)(int) const = MyClass::foo; // ERROR, need explicit address-of MyClass().*myptr(4);
- Ein & liefert einen Pointer auf die Funktion.
- Krishty
- Establishment
- Beiträge: 8268
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Array von Funktionszeigern Compile-Time-konstant
Das klingt äußerst plausibel. Wusste trotz Pointer-Hass und Referenzenliebe garnicht, dass es Funktionsreferenzen gibt … wieder was gelernt :)
Edit:
Edit:
Also, falls in geschwindigkeitskritischen Abschnitten Funktionszeiger auf Template-Funktionen genutzt werden, möglichst den &-Operator weglassen.Microsoft hat geschrieben:The & operator seems to be be giving the notion to compiler that it is uninitialized data. This has a workaround by not using the & operator in the initialization of array.
Considering the priority of the issue and other blocking bugs we have , we will not be able to fix the issue for dev10. We have put the bug in pur database and will be looking at it in future releases.