W mojej dzielonej bibliotece muszę załadować niektóre dane do UnorderDed_map, a ja próbuję to zrobić w funkcji oznaczonej __ atrybut __ ((konstruktor)). Jednak dostałem SIGFPE na każdej operacji mapy. Po niektórych poszukiwaniu stackoverflow odkryłem, że oznacza to, że UnorderDed_map jest niezainicjowany. Jest to dla mnie dość nieoczekiwane i nierozważne, ponieważ w skrócie narusza kontrakty C ++. Każdy może pomóc w jaki sposób mogę uruchomić tę metodę po uruchomieniu konstruktorów? Oto przykład pracujący z moim konstruktorem, który pokazuje, że nie jest nazywany:

#include <stdio.h>

class Ala {
    int i;
public:
    Ala() {
        printf("constructor called\n");
        i = 3;
    }

    int getI() {
        return i;
    }
};

Ala a;

__attribute__((constructor))
static void initialize_shared_library() {
    printf("initializing shared library\n");
    printf("a.i=%d\n", a.getI());
    printf("end of initialization of the shared library\n");
}

Wynikiem jest wynik

initializing shared library
a.i=0
end of initialization of the shared library
constructor called

Jeśli jednak próbuje użyć STD :: COut zamiast printfów, natychmiast trafi do Segfaults (ponieważ konstruktor strumieni nie był uruchomiony)

2
pawel_j 5 czerwiec 2018, 11:27

3 odpowiedzi

Najlepsza odpowiedź

__attribute__((constructor)) to rozszerzenie kompilatora, a więc opuściłeś królestwa standardowego C ++. Wygląda na to, że funkcje konstruktora GCC są uruchamiane przed globalną inicjalizacją.

Sposób naprawienia należy używać innego konstruktu Vanilla C ++, na przykład obiekt globalny, którego inicjalizacją jest prawidłowo sekwencjonowany, definiując go w tym samym TU, co drugi globalny:

Ala a;

static void initialize_shared_library() {
    printf("initializing shared library\n");
    printf("a.i=%d\n", a.getI());
    printf("end of initialization of the shared library\n");
}

static int const do_init = (initialize_shared_library(), 0);
6
Quentin 5 czerwiec 2018, 08:32

Jeśli używasz funkcji, która zwraca zmienną lokalną statyczną, zmienna zostanie zainicjowana przy pierwszym czasie, gdy zostanie wywołana funkcja. Zobacz: Gdy zmienne statyczne na poziomie funkcji są przydzielane / zainicjowane?.

struct Ala {
   // Your code here
   static Ala& get_singleton();
};

Ala& Ala::get_singleton() {
   static Ala singleton;
   return singleton;
}

static void initialize_shared_library() {
    Ala& a = get_singleton();
    printf("initializing shared library\n");
    printf("a.i=%d\n", a.getI());
    printf("end of initialization of the shared library\n");
}

Jak powiedzieli inni, zazwyczaj lepiej jest wykluczyć cały proces inicjalizacji w obiekcie i niech konstruktor wykonuje pracę dla Ciebie (korpus konstruktora jest wykonywany po wszystkich zainicjowanych członków klasy).

1
Jorge Bellon 5 czerwiec 2018, 08:53

Jeśli chcesz uruchomić coś po a jest inicjowane, jest kilka sposobów, aby to zrobić bez pozostawiania standardowego C ++; tutaj jest jeden:

struct Ala2 : Ala
{
    Ala2()
    {
         // your init code here
    }
};

Ala2 a;
0
M.M 5 czerwiec 2018, 08:38