__attribute__((constructor)) äquivalent in VC?

Lesezeit: 4 Minuten

Ich habe mich gefragt, ob es möglich ist, C-Konstruktoren in VC zu verwenden, so wie es möglich ist, sie in GCC zu verwenden.
Der gcc-Weg ist ziemlich gerade mit dem __attribute__ Schlüsselwort, leider scheint VC dieses Schlüsselwort nicht einmal zu kennen, da ich kein Win32-Programmierer bin, frage ich mich, ob es für solche Dinge ein äquivalentes Schlüsselwort gibt.
Nur zur Anmerkung – dies ist ein C-Programm, nicht einmal C++ oder C# (da das in diesen Sprachen ziemlich einfach war)

  • für diejenigen von uns, die es nicht benutzt haben, was macht es? (Und wozu brauchst du es?)

    – jalf

    11. Juli 2009 um 13:24 Uhr

  • Jede Funktion, die als markiert ist constructor wird vom dynamischen Linker ausgeführt, wenn er das Objekt lädt.

    – Adam Goode

    28. April 2010 um 3:12 Uhr

  • @:Jalf: Wie genau funktioniert der Attributkonstruktor?

    – Casebash

    22. September 2010 um 7:36 Uhr


Benutzer-Avatar
Jo

Der folgende C-Code zeigt, wie eine void(void)-Funktion definiert wird, die zur Ladezeit des Programms/der Bibliothek aufgerufen wird, bevor main ausgeführt wird.

Für MSVC platziert dies einen Zeiger auf die Funktion im Benutzerinitialisierungsabschnitt (.CRT$XCU), im Grunde dasselbe, was der Compiler für die Konstruktoraufrufe für statische C++-Objekte tut. Verwendet für GCC ein Konstruktorattribut.

    // Initializer/finalizer sample for MSVC and GCC/Clang.
    // 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>

#ifdef __cplusplus
    #define INITIALIZER(f) \
        static void f(void); \
        struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
        static void f(void)
#elif defined(_MSC_VER)
    #pragma section(".CRT$XCU",read)
    #define INITIALIZER2_(f,p) \
        static void f(void); \
        __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
        __pragma(comment(linker,"/include:" p #f "_")) \
        static void f(void)
    #ifdef _WIN64
        #define INITIALIZER(f) INITIALIZER2_(f,"")
    #else
        #define INITIALIZER(f) INITIALIZER2_(f,"_")
    #endif
#else
    #define INITIALIZER(f) \
        static void f(void) __attribute__((constructor)); \
        static void f(void)
#endif

static void finalize(void)
{
    printf( "finalize\n");
}

INITIALIZER( initialize)
{
    printf( "initialize\n");
    atexit( finalize);
}

int main( int argc, char** argv)
{
    printf( "main\n");
    return 0;
}

  • Hallo Joe: toller Beitrag! Ich brauche wirklich die Tricks für die Arbeit mit VC. Es ist wichtig, eine Komponententestfunktion in C (nicht C++) automatisch zu registrieren. Übrigens: In der zweiten Zeile des Makros INITIALIZER sollte ein abschließendes \ stehen

    – zhaorufei

    27. September 2010 um 1:04 Uhr

  • Solche Konstruktoren werden in neuen Release-Builds von Visual Studio optimiert. Es ist ein selten bekannter und leider ungelöster Fehler. Einziger Workaround den ich bisher gefunden habe: Projekteigenschaften > C/C++ > Optimierung > Whole Program Optimization(/GL) muss deaktiviert sein.

    – Benutzer3042599

    8. Oktober 2015 um 16:27 Uhr


  • Ich habe das gleiche Problem wie oben beschrieben, kopieren Sie also nicht einfach den obigen Code und fügen Sie ihn ein, vorausgesetzt, er funktioniert einfach.

    – CrHasher

    20. November 2015 um 9:32 Uhr

  • GLib hat kürzlich von der Verwendung von .CRT$XCU Abschnitt zur Verwendung DllMain deshalb: bugzilla.gnome.org/show_bug.cgi?id=752837

    – Amro

    21. Dezember 2015 um 23:26 Uhr

  • @ user3042599. Vielen Dank für die Hinweise zu den Problemen mit MSVC 2015 Link-Time-Optimierungen. Ich habe das Codebeispiel bearbeitet und es sollte keine Probleme geben, obwohl es jetzt MSVC 2008 oder höher aufgrund der Verwendung von __pragma() erfordert.

    – Jo

    30. Januar 2016 um 22:22 Uhr

Sie interessieren sich wahrscheinlich für DllMain.

  • Es muss ausgeführt werden Vor Eingabe von main(), das ist für DLLs, wie hängt das zusammen? :/

    nicht so lang

    11. Juli 2009 um 10:43 Uhr

  • Die einzige wirkliche Verwendung für __attribute__((constructor)) besteht darin, sie in gemeinsam genutzten Bibliotheken zu verwenden, ähnlich wie eine DllMain zu emulieren 🙂

    – Nr

    11. Juli 2009 um 11:00 Uhr

  • __attribute__((constructor)) ist sogar in einem einzigen Programm-Image nützlich; zum Beispiel das Einfügen globaler Hooks um Bibliotheks- und Systemaufrufe oder das Registrieren integrierter “Plugins” oder das Initialisieren von Datenstrukturen, die dynamisch verknüpfte Module in ihrem “DllMain“-gleich.

    – vergänglich

    11. Juli 2009 um 16:18 Uhr

Ich glaube nicht, dass es eine Möglichkeit gibt, die Verwendung von C++-Funktionen mit MSVC zu vermeiden. (Die C-Unterstützung von MSVC ist sowieso scheiße.)

Ungetestet, aber dies sollte zumindest ermöglichen, dass derselbe Code sowohl in MSVC als auch in GCC funktioniert.

#if defined(_MSC_VER)
struct construct { construct(void (*f)(void)) { f(); } };
#define constructor(fn) \
    void fn(void); static constructor constructor_##fn(fn)
#elif defined(__GNUC__)
#define constructor(fn)
    void fn(void) __attribute__((constructor))
#endif

static constructor(foo);
void foo() {
    ...
}

  • Soweit ich das beurteilen kann, funktioniert dies nicht in einfachem C auf MSVC 2013 oder 2015. Scheint, als würde der C-Compilermodus Konstruktoren in einer Struktur nicht unterstützen. Ich habe versucht, es auf verschiedene Weise zum Laufen zu bringen.

    – guru_florida

    6. September 2017 um 15:50 Uhr

Ich habe versucht, die letzte Antwort in MSVC wie

#ifdef _MSC_VER
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
        static void f(void); \
        __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
        __pragma(comment(linker,"/include:" p #f "_")) \
        static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
        static void f(void) __attribute__((constructor)); \
        static void f(void)
#endif

aber INITIALIZER(f) kann nicht in 2 verschiedenen Dateien mit demselben Funktionsnamen vorkommen, der an INITIALIZER übergeben wird, die folgende Definition erlaubt dies

#ifdef _MSC_VER
#define INITIALIZER(f) \
    static void f();\
    static int __f1(){f();return 0;}\
    __pragma(data_seg(".CRT$XIU"))\
    static int(*__f2) () = __f1;\
    __pragma(data_seg())\
    static void f()
#else
#define INITIALIZER(f) \
    __attribute__((constructor)) static void f()
#endif

1385010cookie-check__attribute__((constructor)) äquivalent in VC?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy