(erledigt) [C++] Array Funktionszeiger Compile-Time-konstant

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

(erledigt) [C++] Array Funktionszeiger Compile-Time-konstant

Beitrag von Krishty »

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.
Zuletzt geändert von Krishty am 22.06.2010, 21:55, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
zwergmulch
Beiträge: 91
Registriert: 07.12.2009, 16:42
Echter Name: Fabian R

Re: [C++] Array von Funktionszeigern Compile-Time-konstant

Beitrag von zwergmulch »

Das sollte vlt. mit constexpr aus C++0x gehen. Wird aber imho noch nicht von VS 2010 unterstützt.
Bild
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array von Funktionszeigern Compile-Time-konstant

Beitrag von Krishty »

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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
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

Beitrag von Aramis »

afaik sind Win32-PEs ja kein position-independent code?
Ja, relocatable (mit den bekannten Vor– und Nachteilen im Vergleich zu Linux’ ELF). Die /FIXED–Option fuer den Linker hast du probiert?
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array von Funktionszeigern Compile-Time-konstant

Beitrag von Krishty »

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?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
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

Beitrag von Aramis »

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.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array von Funktionszeigern Compile-Time-konstant

Beitrag von Krishty »

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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
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

Beitrag von Aramis »

Der Stack ist von Dynamic Basing nicht betroffen, denke ich. Nur die Stelle, an der das Betriebsystem PE–Images in den Adressraum hineinmap’d.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array von Funktionszeigern Compile-Time-konstant

Beitrag von Krishty »

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.
Zuletzt geändert von Krishty am 06.06.2010, 21:30, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
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

Beitrag von Aramis »

Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array von Funktionszeigern Compile-Time-konstant

Beitrag von Krishty »

Okay, habe es: Wird das Array so initialisiert

Code: Alles auswählen

static void (* const Functions[])() = { &FuncA, &FuncB };
, landet für jedes Element ein mov in der Exe. Wird das Array so initialisiert

Code: Alles auswählen

static void (* const Functions[])() = { FuncA, FuncB };
, 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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
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

Beitrag von Aramis »

Ist es legal, Funktionsadressen mit & abzufragen?
Ich mag mich schon wieder irren, aber ich glaube, ‘&’ auf eine Funktion angewandt liefert einen Pointer auf sie, einfach nur der Funktionsname eine Referenz.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array von Funktionszeigern Compile-Time-konstant

Beitrag von Krishty »

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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array von Funktionszeigern Compile-Time-konstant

Beitrag von Krishty »

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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
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

Beitrag von Aramis »

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.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array von Funktionszeigern Compile-Time-konstant

Beitrag von Krishty »

Das klingt äußerst plausibel. Wusste trotz Pointer-Hass und Referenzenliebe garnicht, dass es Funktionsreferenzen gibt … wieder was gelernt :)

Edit:
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.
Also, falls in geschwindigkeitskritischen Abschnitten Funktionszeiger auf Template-Funktionen genutzt werden, möglichst den &-Operator weglassen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten