dlaczego SIGSEGV przed uruchomieniem main()

0

Czy mogę prosić o wyjaśnienie dlaczego pojawia sie SIGSEGV na platformie Linux ?
Wyjątek jest zanim uruchomi się main, minimalny kawałek kodu który powoduje wyjątek

#include <cstdio>

#include <ftd2xx.h>

// /** @{
//  * @name FT_STATUS
//  * @details Return status values for API calls.
//  */
// typedef ULONG	FT_STATUS;

FT_STATUS stat;

int main()
{
    printf("main\n");
    FT_HANDLE m_dev_handle;
    FT_Close(m_dev_handle);
}

Warunki konieczne aby pojawił się wyjątek:

  1. -lftd2xx , nie ma znaczenia czy biblioteka jest statyczna czy dynamiczna
  2. #include <ftd2xx.h>
  3. użycie w kodzie dowolnej funkcji z biblioteki ftd2xx FT_***
  4. zadeklarowanie globalnej zmiennej typu FT_STATUS

Dlaczego zadeklarowana globalna zmienna która nawet nie jest używana powoduje wyjątek szczególnie że jest to typ prosty ULONG ?

screenshot-20240522084922.png

Zastanawia mnie co się zmienia pomiędzy wersjami w kontekście biblioteki że jedna wersja nie działa:

// ta wersja nie dziala
FT_STATUS stat;
int main()
{

a taka wersja działa

int main()
{
  FT_STATUS stat;
5

Hmm na call stacku masz funkcje o nazwie stat i zadeklarowałeś globalną zmienną stat.
W C++ jest mangling nazw w C nie ma, więc teoretycznie symbole powinny być takie same dla zmiennej i funkcji.

Mógłbyś wejść do tej funkcji stat, bo kodów źródłowych nie ma i zobaczy co ona tam robi, czy strace jakie systemowe wywołanie robi, z jakim adresem.
Co jest pod tym adresem, jakaś analiza tego.

1

Co podaje ldd ?
Biblioteka z pakietu, sam kompilowałeś czy ściągnąłeś z sieci binarke?

1

To co pisze @GodOfCode zdaje się mieć sens. Jeśli nie chcesz deklarować zmiennej stat w mainie to zrób ją jako static, powinno pomóc. Inna nazwa zmiennej też.

0

Przyczyna sie wyjasniła !
To co napisał @.GodOfCode. jest przyczyną, typ zmiennej nie ma znaczenia tylko nazwa stat powoduje zamieszanie czyli nawet taka wersja int stat; tez powoduje wyjątek.
Sprawdziłem co importuje biblioteka libftd2xx.a i na liscie jest funkcja stat. https://www.man7.org/linux/man-pages/man2/stat.2.html

Wszystko jasne.

mea culpa, mea culpa,
mea máxima culpa.

7

czemu piszesz "mea culpa, mea culpa,"?
To jest jeden z większych WTF linker-a. Linker powinien podnieść tu alarm, a tego nie robi.
Zauważenie tego problemu jest dość trudne.
To jest powód dla którego dodano namespace do C++.

0

@MarekR22 ja uznałem ze po części przyczyniłem się do błędu, bo zadeklarowałem globalna zmienną i pech chciał że nazwa to akurat funkcja która gdzieś istnieje też w globalnej przestrzeni.
Kompilator nie był w stanie tego wyłapać, bo wyłapie tylko funkcje które są w plikach .h
Ale zgodzę się z tym że linker powinien chociaż warningiem mnie uraczyć.

Czy twórcy gcc wiedzą o tym problemie ?
Czy to nie ma sensu zgłaszać bo i tak nikt z tym nic nie robi bo jest to cześć standardu c++ :D

1
Marius.Maximus napisał(a):

Czy twórcy gcc wiedzą o tym problemie ?

Tak to jest znany problem, dla którego nie ma prostego rozwiązania.
Na SO widziałem analogiczny problem z inną funkcją o jeszcze bardziej dziwnej nazwie (nie pamiętam teraz co to było).

0

To była lekcja programowania pod tytułem: "Niebezpieczeństwa używanie zmiennych globalnych" 😀

Wnioski:

  1. Najlepiej nie używać globalnych zmiennych
  2. w ostateczności nazwa misi być "fikuśna" aby zmniejszyć prawdopodobieństwo kolizji
1
MarekR22 napisał(a):
Marius.Maximus napisał(a):

Czy twórcy gcc wiedzą o tym problemie ?

Tak to jest znany problem, dla którego nie ma prostego rozwiązania.
Na SO widziałem analogiczny problem z inną funkcją o jeszcze bardziej dziwnej nazwie (nie pamiętam teraz co to było).

Pewnie coś z tego:

$ man y0

Y0(3)                      Linux Programmer's Manual                     Y0(3)

NAME
       y0, y0f, y0l, y1, y1f, y1l, yn, ynf, ynl - Bessel functions of the second kind
1

Nie zapomnij nawrzucać producentowi na adres supportu klienta.

0
Marius.Maximus napisał(a):

To była lekcja programowania pod tytułem: "Niebezpieczeństwa używanie zmiennych globalnych" 😀

Wnioski:

  1. Najlepiej nie używać globalnych zmiennych
  2. w ostateczności nazwa misi być "fikuśna" aby zmniejszyć prawdopodobieństwo kolizji

Bracie @Marius.Maximus generalnie wnioski słuszne, przy czym 1 to powinien być "jeśli już używać zmiennych globalnych, to z głową".
Ja postępuję w taki sposób, np. dla QStringów definiujących jakieś identyfikatory:

//mam sobie plik który zowię definitions.h, a w nim
namespace Global
{
  namespace Constants
  {
    namespace Math
    {
      const double pi = 3.14;
    }
    namespace Physics
    {
      const double accelerationEarth = 9.81;
    }
  }

  namespace Database
  {
     const QString databaseName = "some name";
  }
}

//i potem używanie tego jest bardzo proste, intuicyjne i samodokumentujące się dzięki podpowiedziom IDE - o ile się te namespace'y dobrze ponazywa
#include "definitions.h"

double circleArea = Global::Constants::Math::pi * radius * radius;

Poza tym, robię je tylko jako read-only, unikam jak ognia jakiegokolwiek zapisywania do nich poza inicjalizacją.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.