IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Segmentation fault seulement avec gdb


Sujet :

C++

  1. #1
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 190
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 190
    Points : 17 146
    Points
    17 146
    Par défaut Segmentation fault seulement avec gdb
    Bonjour à tous!
    Après si longtemps loin de nos chers forums, me voici de retour avec un problème assez coriace.

    J'ai un programme pour Windows qui fonctionne bien en temps normal:
    • Son manifeste exige les droits d'administrations, et windows s'assure qu'il soit lancé avec.
    • Son IHM Qt s'affiche, je peux intéragir avec,
    • L'accès au périphérique usb essentiel au travail se fait correctement,
    • etc

    Quand j'ouvre une console admin et le lance directement, sans argument, tout se passe bien.
    Par contre, si je le lance dans un gdbserver, je rencontre une segfault systématiquement, et avant main.

    Je sèche complètement, sans une once de piste. Auriez-vous une idée?

    Un peu de contexte plus précis.
    Le soft est compilé pour un windows 10, mais depuis un environnement docker linux: un ubuntu 20.04 avec entre autre les paquets officiel mingw et gdb-mingw-w64 et gdb-mingw-w64-target.
    La compilation est pilotée par CMake,
    Qt est compilé en bibliothèques statiques dans le même docker.
    Le programme est lié avec -static-libstdc++ -static-libgcc
    Le programme est compilé en debug (incluant -g -ggdb)

    La procédure de débug concrète:
    1. Entrer dans le docker
    2. Compiler le soft sur le pc cible, dans un dossier vide, (Normalement il est sans dépendance).
    3. copier aussi /usr/share/win32/gdbserver.exe, ainsi que ses dépendances, /usr/lib/gcc/i686-w64-mingw32/*-win32/lib{stdc++*.dll,gcc_s*.dll}
    4. sur le pc cible ouvrir une console avec droit d'admin et cd dans le dit dossier
    5. gdbserver.exe <une ip>:3636 Programme.exe
    6. gdbserver se lance, affiche qu'il attends une connexion.
    7. Sur le pc de build, toujours dans le docker, lancer i686-w64-mingw32-gdb Programme.exe
    8. quand le binaire est chargé (pour les symboles de débug), target remote <ip du pc window>:3636
    9. gdb charge les dlls windows.
    10. continue
    11. la segfault se produit systématiquement.

    Si en 5) je fais juste Programme.exe tout se passe bien.

    gdb affiche
    $ i686-w64-mingw32-gdb Programme.exe 
    Reading symbols from Programme.exe...
    (gdb) target remote <ip windows>:3636
    Remote debugging using <ip windows>:3636
    Reading C:/WINDOWS/SYSTEM32/ntdll.dll from remote target...
    warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
    Reading C:/WINDOWS/System32/kernel32.dll from remote target...
    Reading C:/WINDOWS/System32/KernelBase.dll from remote target...
    Reading C:/WINDOWS/SYSTEM32/apphelp.dll from remote target...
    Reading C:/WINDOWS/System32/advapi32.dll from remote target...
    Reading C:/WINDOWS/System32/msvcrt.dll from remote target...
    Reading C:/WINDOWS/System32/sechost.dll from remote target...
    Reading C:/WINDOWS/System32/rpcrt4.dll from remote target...
    Reading C:/WINDOWS/System32/sspicli.dll from remote target...
    Reading C:/WINDOWS/System32/cryptbase.dll from remote target...
    Reading C:/WINDOWS/System32/bcryptprimitives.dll from remote target...
    Reading C:/WINDOWS/System32/gdi32.dll from remote target...
    Reading C:/WINDOWS/System32/win32u.dll from remote target...
    Reading C:/WINDOWS/SYSTEM32/FWPUCLNT.DLL from remote target...
    Reading C:/WINDOWS/SYSTEM32/dsound.dll from remote target...
    Reading C:/WINDOWS/System32/gdi32full.dll from remote target...
    Reading C:/WINDOWS/System32/bcrypt.dll from remote target...
    Reading C:/WINDOWS/System32/msvcp_win.dll from remote target...
    Reading C:/WINDOWS/System32/powrprof.dll from remote target...
    Reading C:/WINDOWS/System32/ucrtbase.dll from remote target...
    Reading C:/WINDOWS/System32/umpdc.dll from remote target...
    Reading C:/WINDOWS/System32/user32.dll from remote target...
    Reading C:/WINDOWS/System32/combase.dll from remote target...
    Reading C:/WINDOWS/System32/imm32.dll from remote target...
    Reading C:/WINDOWS/System32/ole32.dll from remote target...
    Reading C:/WINDOWS/SYSTEM32/winmm.dll from remote target...
    Reading C:/WINDOWS/SYSTEM32/IPHLPAPI.DLL from remote target...
    Reading C:/WINDOWS/System32/oleaut32.dll from remote target...
    Reading C:/WINDOWS/System32/shell32.dll from remote target...
    Reading C:/WINDOWS/SYSTEM32/winmmbase.dll from remote target...
    Reading C:/WINDOWS/System32/cfgmgr32.dll from remote target...
    Reading C:/WINDOWS/System32/SHCore.dll from remote target...
    Reading C:/WINDOWS/System32/windows.storage.dll from remote target...
    Reading C:/WINDOWS/System32/profapi.dll from remote target...
    Reading C:/WINDOWS/System32/shlwapi.dll from remote target...
    Reading C:/WINDOWS/System32/kernel.appcore.dll from remote target...
    Reading C:/WINDOWS/System32/cryptsp.dll from remote target...
    Reading C:/WINDOWS/System32/ws2_32.dll from remote target...
    Reading C:/WINDOWS/SYSTEM32/WinSCard.dll from remote target...
    Reading C:/WINDOWS/SYSTEM32/wininet.dll from remote target...
    Reading C:/WINDOWS/SYSTEM32/wsock32.dll from remote target...
    Reading C:/WINDOWS/SYSTEM32/devobj.dll from remote target...
    0x7778eaa3 in ntdll!LdrInitShimEngineDynamic () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    
    (gdb) continue
    Continuing.
    
    Thread 1 received signal SIGSEGV, Segmentation fault.
    0x6d157d0b in WinSCard!SCardCancel () from target:C:/WINDOWS/SYSTEM32/WinSCard.dll
    (gdb) bt
    #0  0x6d157d0b in WinSCard!SCardCancel () from target:C:/WINDOWS/SYSTEM32/WinSCard.dll
    #1  0x6d15bf2a in WinSCard!ClassInstall32 () from target:C:/WINDOWS/SYSTEM32/WinSCard.dll
    #2  0x6d153758 in ?? () from target:C:/WINDOWS/SYSTEM32/WinSCard.dll
    #3  0x6d1578ea in WinSCard!SCardCancel () from target:C:/WINDOWS/SYSTEM32/WinSCard.dll
    #4  0x6d15712d in WinSCard!SCardCancel () from target:C:/WINDOWS/SYSTEM32/WinSCard.dll
    #5  0x77751de6 in ntdll!RtlFreeUserStack () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    #6  0x77715608 in ntdll!RtlGetNtSystemRoot () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    #7  0x6d156ff0 in WinSCard!SCardCancel () from target:C:/WINDOWS/SYSTEM32/WinSCard.dll
    #8  0x77723f8f in ntdll!RtlCompareUnicodeStrings () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    #9  0x77724836 in ntdll!RtlMultiByteToUnicodeSize () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    #10 0x7772484d in ntdll!RtlMultiByteToUnicodeSize () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    #11 0x77789542 in ntdll!RtlCaptureStackContext () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    #12 0x77789382 in ntdll!RtlCaptureStackContext () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    #13 0x77731dd1 in ntdll!LdrInitializeThunk () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    #14 0x77731cc1 in ntdll!LdrInitializeThunk () from target:C:/WINDOWS/SYSTEM32/ntdll.dll
    #15 0x00000000 in ?? ()
    (gdb) 
    WinSCard est un module du runtime de windows, qui permet d'accéder aux "smart cards", qui est mon matériel essentiel (une sorte de carte à puce)

    Fait amusant, je peux faire un continue, et le main commence alors, la vérification des arguments de ligne de commande est faite, puis j'aurai une boucle infinie qui se crée, vers la création de l'IHM.

    Autres informations possiblement pertinente:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $ i686-w64-mingw32-gdb -v
    GNU gdb (GDB) 9.1
    Copyright (C) 2020 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
     
    $ i686-w64-mingw32-gcc -v
    Using built-in specs.
    COLLECT_GCC=i686-w64-mingw32-gcc
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-w64-mingw32/9.3-win32/lto-wrapper
    Target: i686-w64-mingw32
    Configured with: ../../src/configure --build=x86_64-linux-gnu --prefix=/usr --includedir='/usr/include' --mandir='/usr/share/man' --infodir='/usr/share/info' --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir='/usr/lib/x86_64-linux-gnu' --libexecdir='/usr/lib/x86_64-linux-gnu' --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr --enable-shared --enable-static --disable-multilib --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --libdir=/usr/lib --enable-libstdcxx-time=yes --with-tune=generic --with-headers=/usr/i686-w64-mingw32/include --enable-version-specific-runtime-libs --enable-fully-dynamic-string --enable-libgomp --enable-languages=c,c++,fortran,objc,obj-c++,ada --enable-lto --enable-threads=win32 --program-suffix=-win32 --program-prefix=i686-w64-mingw32- --target=i686-w64-mingw32 --with-as=/usr/bin/i686-w64-mingw32-as --with-ld=/usr/bin/i686-w64-mingw32-ld --enable-libatomic --enable-libstdcxx-filesystem-ts=yes --enable-dependency-tracking
    Thread model: win32
    gcc version 9.3-win32 20200320 (GCC)

    CMake utilise les flags de compilation suivant:
    Code makefile : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # CMAKE generated file: DO NOT EDIT!
    # Generated by "Unix Makefiles" Generator, CMake Version 3.16
     
    # compile CXX with /usr/lib/ccache/i686-w64-mingw32-g++
    # compile RC with i686-w64-mingw32-windres
    CXX_FLAGS = -g -ggdb   -Wall -Wextra -Wctor-dtor-privacy -Woverloaded-virtual -Wold-style-cast -Wformat -Wformat-security -Werror=format-security -Wuninitialized -Winit-self -Wpointer-arith -fno-stack-protector -DDEBUG -D__STDC_FORMAT_MACROS -std=c++11
     
    CXX_DEFINES = -DNOMINMAX -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_STATICPLUGIN -DQT_WIDGETS_LIB -DUNICODE -D_UNICODE -D_WIN32_WINNT=0x0601
     
    CXX_INCLUDES = @CMakeFiles/Programme.dir/includes_CXX.rsp
     
    RC_FLAGS =   -DDEBUG -D__STDC_FORMAT_MACROS
     
    RC_DEFINES = -DCRYPTOSMART_TYPES_TEST_SUPPORT -DNOMINMAX -DNO_DRIVERLESS -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_STATICPLUGIN -DQT_WIDGETS_LIB -DSDK_TEST_SUPPORT -DUNICODE -D_UNICODE -D_WIN32_WINNT=0x0601
     
    RC_INCLUDES = -I~/Programe/build_windows_debug -I~/Programe -I~/Programe/build_windows_debug/Programme_autogen/include -I~/Programe/include -I~/Programe/include/Widgets -I~/artifacts/sdk-client/windows/debug/include -I~/artifacts/External/windows/debug/include/mbedtls-2.16 -I/opt/qt-win32-release-static/include -I/opt/qt-win32-release-static/include/QtWidgets -I/opt/qt-win32-release-static/include/QtGui -I/opt/qt-win32-release-static/include/QtCore -I/opt/qt-win32-release-static/./mkspecs/win32-g++ -I/opt/qt-win32-release-static/include/QtNetwork
    Code makefile : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #CMakeFiles/Programme.dir/includes_CXX.rsp
    -I~/Programme/build_windows_debug
    -I~/Programme
    -I~/Programme/build_windows_debug/Programme_autogen/include
    -I~/Programme/include
    -I~/Programme/include/Widgets
    -isystem ~/artifacts/sdk-client/windows/debug/include
    -isystem ~/artifacts/External/windows/debug/include/mbedtls-2.16
    -isystem /opt/qt-win32-release-static/include
    -isystem /opt/qt-win32-release-static/include/QtWidgets
    -isystem /opt/qt-win32-release-static/include/QtGui
    -isystem /opt/qt-win32-release-static/include/QtCore
    -isystem /opt/qt-win32-release-static/./mkspecs/win32-g++
    -isystem /opt/qt-win32-release-static/include/QtNetwork
    L'édition de lien:
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    /usr/lib/ccache/i686-w64-mingw32-g++ -g -ggdb  -static -mwindows -Wl,--whole-archive CMakeFiles/Programme.dir/objects.a -Wl,--no-whole-archive  -o Programme.exe -Wl,--out-implib,libProgramme.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/Programme.dir/linklibs.rsp
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    #linklibs.rsp
    /opt/qt-win32-release-static/plugins/bearer/libqgenericbearer.a
    /opt/qt-win32-release-static/plugins/bearer/libqnativewifibearer.a
    /opt/qt-win32-release-static/plugins/platforms/libqwindows.a
    /opt/qt-win32-release-static/lib/libQt5Widgets.a
    /opt/qt-win32-release-static/lib/libQt5Network.a
    /opt/qt-win32-release-static/lib/libQt5Gui.a
    /opt/qt-win32-release-static/lib/libQt5Core.a
    /opt/qt-win32-release-static/lib/libqtpcre.a
    /opt/qt-win32-release-static/lib/libqtpng.a
    /opt/qt-win32-release-static/lib/libqtharfbuzzng.a
    /opt/qt-win32-release-static/lib/libQt5PlatformSupport.a
    -limm32
    -lopengl32
    -liphlpapi
    -lws2_32
    -lrpcrt4
    -lfwpuclnt
    ~/artifacts/sdk-client/windows/debug/lib/libSDK.a
    ~/artifacts/External/windows/debug/lib/libspeex.a
    ~/artifacts/External/windows/debug/lib/libpcre.a
    ~/artifacts/External/windows/debug/lib/libminizip.a
    ~/artifacts/External/windows/debug/lib/libzlib.a
    -lwsock32
    -lws2_32
    -lwininet
    -lwinmm
    -ldsound
    -lwinscard
    -lksuser
    -lwbemuuid
    ~/artifacts/External/windows/debug/lib/libsqlite.a
    ~/artifacts/External/windows/debug/lib/libmbedtls.a
    -static-libgcc
    -static-libstdc++
    -static-libgcc
    -static-libstdc++
    /opt/qt-win32-release-static/lib/libqtmain.a
    -lws2_32
    -lrpcrt4
    -lfwpuclnt
    -lkernel32
    -luser32
    -lgdi32
    -lwinspool
    -lshell32
    -lole32
    -loleaut32
    -luuid
    -lcomdlg32
    -ladvapi32
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 617
    Points : 30 639
    Points
    30 639
    Par défaut
    Salut,

    1. Que se passe-t-il lorsque tu essaye de débugger ton programme en local (donc, sans passer par gdbserver), si tu as l'occasion d'essayer
    2. Que se passe-t-il lorsque tu lance, tout simplement, ton application (avec les droits nécessaire) sans passer par le débuggeur
    3. As-tu un accès quelconque au code source de WinScard
    4. (la base métier de ton projet est-elle suffisamment indépendante de l'IHM que pour te permettre de lancer le programme en mode console si oui, que donne le fait de lancer le programme en mode console )
    5. question idiote (quoi que...) un serveur X est-il installé sur le docker



    Personnellement, je pencherais volontiers pour un pointeur laissé (ou arrivant) non initialisé dans la fonction SCardCancel.

    Je présumes cependant que l'appl à cette fonction se fait sans doute lors de l'initialisation même du programme, bien avant que l'IHM n'entre en jeu; ce qui risque de compliquer énormément les choses si tu souhaite mettre un break point avant l'appel de cette fonctions

    Car, de manière générale, c'est sans doute le meilleur conseil à te donner: essaye de placer un breakpoint avant le premier appel de la fonction fautive et vérifie les globales (surtout les pointeurs), afin de pouvoir déterminer les raisons qui font que tu te retrouves avec cette erreur de segmentation (qui est, classiquement, le signe qu'un dangling pointer / un pointeur null a tenté d'être dé référencé ), et donc comment y remédier, et à partir de où
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 617
    Points : 30 639
    Points
    30 639
    Par défaut
    Bon, je vais -- pour une fois, me répondre à moi-même:
    3. As-tu un accès quelconque au code source de WinScard
    Après une rapide recherche: Non, WinSCard fait partie de l'API windows, ce qui fait que nous sommes face à une de ces boites noires dont windows a le secret

    Par contre, cette recherche a ouvert une nouvelle voie dans mon esprit, dans le sens où je présumes (tu me diras si j'ai tord ou non ) que, lors du lancement du programme, tu commence tout simplement par t'assurer de la présence du lecteur de carte, sans essayer de récupérer les info de la carte à puce qui n'est d'ailleurs peut-être pas encore insérée dedans, juste pour pouvoir rappeler à l'utilisateur qu'il doit connecter le lecteur.

    Comme la fonction SCardCancel prend un handle vers le gestionnaire de context requis pour utiliser WinScard, je me demande si, d'une manière ou d'une autre, tu n'aurais -- tout simplement -- pas fait appel à cette fonction alors que le contexte requis a déjà été détruit suite à l'appel à la fonction SCardReleaseContext.

    Peut-être -- ne connaissant pas le code, je part en évaluation free style -- pourrait-il tout simplement suffire d'intervertir ces deux appels, SCardCancel permettant d'interrompre l'attente des fonctionnalités blocantes invoquées sur le contexte en question, mais nécessitant un contexte actif, SCardReleaseContext permettant de libérer les ressources du contexte une fois qu'il est devenu inutile.

    D'ailleurs, à bien y penser: est-il vraiment nécessaire / utile de clôturer directement le contexte créé pour la vérification de la présence du lecteur de cartes ne pourrait-on pas envisager de garder ce contexte actif pour tout le temps durant lequel l'application fonctionne et de l'utiliser (comprend: de ne pas créer de nouveau contexte) à chaque fois qu'une carte doit être lue

    [EDIT] Bon, j'ai bien conscience que, sur un programme nécessitant les droit d'administrateur, l'idée de garder un contexte sur une ressource "sensible" n'est clairement pas ce qui se fait de plus sécuritaire. Mais bon, en attendant, cela pourrait te sortir une sérieuse épine du pied
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    Ca ne fera peut-être pas avancer le bazar mais :

    - as-tu essayé de builder le même programme mais directement sous Windows avec mingw64 ?
    - as-tu essayé de faire un programme minimaliste qui fait un hello world en console et qui suit le process complet depuis Linux jusqu'au gdbserver ?
    - idem mais avec un hello world en Qt ?

    PS : ça fait plaisir de te voir

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 190
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 190
    Points : 17 146
    Points
    17 146
    Par défaut
    Réponses à toutes ces questions:
    @koala01
    Je n'ai pas encore essayé d'utiliser un gdb local.

    L'application sans débuggeur fonctionne, l'ihm apparait, et me signale si le lecteur n'est pas joignable, ou me permet d'interagir avec.

    Non, le programme en lui-même ne se lance pas en mode console. Cela dit, j'ai un autre programme dédié au mode console.

    Je n'ai pas de serveur X dans mon docker, du moins pas que je sache, et gdb laisse l'affichage sur le poste client, normalement. Cela dit, c'est une piste loin d'être idiote

    @Bktero
    Non, je n'ai pas test de builder avec mingw depuis windows. Je peux tenter.

    Oui, j'ai tenté un programme simple, et ca passe

    Non, pas le hello world Qt, je n'y connais rien.

    PS:
    Moi aussi, je suis contente d'être revenue, et de voir que vous y êtes toujours
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 190
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 190
    Points : 17 146
    Points
    17 146
    Par défaut
    Complément d'information, le programme console présente le même symptome.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 617
    Points : 30 639
    Points
    30 639
    Par défaut
    Après quelques recherches dans le but te t'aider, j'ai pu constater que le type SCARDCONTEXT n'est jamais qu'un typedef de ULONG_PTR, autrement dit, un pointeur casté en unsigned long; ce qui semble parfaitement cohérent avec l'apparition d'une erreur de segmentation

    Je te proposerais donc de reprendre depuis le début:

    Ton erreur de segmentation survient, de toutes évidences, lors d'un appel à la fonction SCardCancel. Bien qu'il s'agisse d'une des boites noires dont microsoft a le secret, on peut donc "raisonnablement" penser que cette fonction va essayer de dé référencer le pointeur qui lui est fourni et que ce pointeur est devenu invalide.

    Cela semble d'autant plus raisonnable que les deux principales fonctions que l'on utilise pour gérer le lecteur de carte sont:
    1. SCardEstablishContext, qui prend un pointeur sur un SCARDCONTEXT (autrement dit: un pointeur de pointeur) pour créer le contexte (logique: vu qu'il faut donner l'adresse du contexte au SCARDCONTEXT ) et
    2. SCardReleaseContext qui elle, prend un SCARDCONTEXT comme paramètre

    Voilà qui ouvre une nouvelle voie de réflexion, car cela implique que SCardReleaseContext ne va pas modifier l'adresse représentée par notre contexte après l'avoir détruit, ce qui, comme tu le sais bien, nous provoque un joli dandling pointer

    Je commencerais donc par traquer les appels à SCardReleaseContext pour m'assurer que le contexte est systématiquement remis à null après l'appel de cette fonction. Cela n'empêchera peut-être pas l'erreur de segmentation, mais, au moins, cela nous permettra de vérifier la validité du contexte avant de faire appel à SCardCancel

    Ensuite, je traquerais l'ensemble des appels à SCardCancel (qui ne devraient pas être si nombreux au niveau de l'initialisation de l'application ) pour m'assurer que ces appels soient bien conditionnés à la validité du contexte que l'on s'apprête à leur transmettre, sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if(le_contexte != nullptr){ // je sais, je suis inutilement verbeux, mais c'est explicite :D
        SCardCancel(le_contexte);
    }
    On pourrait d'ailleurs "décemment" estimer que la validité du contexte à transmettre à SCardCancel est une (en fait la) précondition requise à l'appel de la fonction, et que tout appel à cette fonction avec un contexte invalide devrait être considéré comme une erreur de programmation

    Si les différents appels à SCardCancel ne sont pas disséminés dans tout ton code, l'utilisation d'une assertion au lieu du test que je présente ici serait sans doute la bienvenue, étant donné qu'elle t'obligerait à corriger l'ensemble du code qui y fait indument appel

    Par contre, si les appels à SCardCancel sont dissiminés dans ton code, étant donné que c'est une fonction spécifique à ce que l'on peut assimiler à "une bibliothèque externe" (fut-elle fournie par le système d'exploitation ) il serait peut-être opportun de "l'encapsuler" dans une fonction "bien à toi", afin que l'assertion soit toujours utilisée

    Bien sur, je n'ai pas ton code sous les yeux (et je présumes qu'il est suffisamment "secret" pour que tu ne puisse pas te permettre de nous le montrer, autrement, tu l'aurais sans doute déjà fait ).

    Cela m'empêche d'être beaucoup plus précis, quand bien même je souhaiterais l'être et m'oblige en revanche à faire une série de déductions qui sont peut-être totalement foireuses.

    Je crois cependant que ces déductions ne sont pas aussi foireuses que cela et que cette piste mérite d'être suivie
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 190
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 190
    Points : 17 146
    Points
    17 146
    Par défaut
    Mon soucis premier, c'est que j'ai ce problème AVANT l'appel de main().
    Du coup, je n'ai pas de code à montrer.

    J'ai deux pistes:
    - soit il se passe quelque chose dans le préambule propre à mingw64, qui est buggé lorsque je mets mon gdb
    - soit j'ai une variable globale mal gérée, et je tombe soit sur le problème de l'ordre initialisation statique, soit une mauvaise initialisation.

    Cette deuxième piste me semble plus probable, mais je ne la trouve pas.

    Ce qui me perturbe le plus, c'est que le problème n'apparait pas "seulement en débug", mais "seulement quand lancé depuis un gdbserver".
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 116
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 116
    Points : 32 968
    Points
    32 968
    Billets dans le blog
    4
    Par défaut
    Un cas tordu de pointeur global non initialisé qui a une valeur mytho sans gdb mais avec gdb il se retrouve null et crash lors de son accès ?
    J'ai eu un cas similaire il y a quelques mois et c'était silencieux grâce aux allocateurs et pools mémoires.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 341
    Points : 4 171
    Points
    4 171
    Par défaut Carte et sécurité ?
    Bonjour,

    Peut être est-ce hors de propos, mais les pilotes de cartes sécurisés sont eux-mêmes sécurisés et tentent de se protèger de toute intrusion qui permettrait, par exemple, de récupérer les codes en plaçant un hook. De là à ce que cela n'aime pas les debugger...

    Salutations
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Vu l'aspect de la StackTrace, je pense que SCardCancel n'est pas vraiment la fonction où sa plante, parce qu'il y a peu de raison qu'une telle fonction s'appelle récursivement. Je pense que ça pète plutôt dans des fonctions non-exportées, et SCardCancel() n'est que la fonction exportée la plus proche à avoir une adresse inférieure.

    Ce que je trouve bizarre aussi, c'est le "received signal SIGSEGV" alors qu'un process Windows n'utilise pas les signaux, mais les exceptions Win32... et le debugger n'explique pas si l'exception est unhandled ou pas (il a déjà existé du code qui s'attend à une EXCEPTION_ACCESS_VIOLATION et sait la gérer, donc ça ne serait pas la première fois)

    As-tu tenté d'exécuter ton programme dans un autre debugger, explicitement dédié à Windows?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 190
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 190
    Points : 17 146
    Points
    17 146
    Par défaut
    C'est pour ca que je suis en train de créer un programme court, qui utilise un code proche pour accéder à la carte. Et j'ai obtenu le même problème.
    Concrètement, je seche de plus en plus.

    Mais comme on est sur du code type "C with class", avec quelques tentatives de bien faire par endroit, je désespère un peu.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  13. #13
    Membre éprouvé
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 562
    Points : 1 253
    Points
    1 253
    Par défaut
    Salut,

    Citation Envoyé par ternel Voir le message
    C'est pour ca que je suis en train de créer un programme court, qui utilise un code proche pour accéder à la carte. Et j'ai obtenu le même problème.
    Au lieu de la liaison statique de cette dll, à titre personnel, je tenterais bien son chargement dynamique (LoadLibrary, GetProcAddress, GetModuleHandle... ) pour voir.

  14. #14
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 190
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 190
    Points : 17 146
    Points
    17 146
    Par défaut
    Malheureusement, la liaison statique est un prérequis opérationnel…
    Cela dit, l'idée est intéressante.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  15. #15
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 341
    Points : 4 171
    Points
    4 171
    Par défaut
    Bonjour Medinoc,

    Citation Envoyé par Médinoc Voir le message
    Vu l'aspect de la StackTrace, je pense que SCardCancel n'est pas vraiment la fonction où sa plante, parce qu'il y a peu de raison qu'une telle fonction s'appelle récursivement.
    L'une des nombreuses techniques de protection (si tant est que cette hypothèse est valide ici) consiste à retourner un mauvais pointeur. Ainsi l'erreur se manifeste hors de l'appel proprement dit et rend le pistage et donc un éventuel contournement plus difficile. Il est assez facile (notamment grâce aux temps et l'état des caches processeur) pour une application (ou un pilote) de détecter si elle s'exécute en mode debug et d'adapter son comportement.

    Salutations
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

Discussions similaires

  1. [NASM / Linux][Débutant] Segmentation fault affichage avec printf
    Par donkeyquote dans le forum x86 32-bits / 64-bits
    Réponses: 4
    Dernier message: 02/11/2008, 19h00
  2. Segmentation fault avec glCompressedTexImage2DARB
    Par patbier dans le forum OpenGL
    Réponses: 5
    Dernier message: 12/12/2005, 10h32
  3. pb avec un warning et un segmentation fault
    Par salseropom dans le forum C
    Réponses: 10
    Dernier message: 30/11/2005, 16h48
  4. sprintf avec gcc4 : Segmentation Fault
    Par stephane_bou dans le forum C
    Réponses: 3
    Dernier message: 26/11/2005, 20h02
  5. Pb segmentation fault avec glutinit()
    Par pipistrelle dans le forum GLUT
    Réponses: 2
    Dernier message: 17/11/2004, 23h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo