begin process at 2012 05 29 08:02:12
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C

 > 

Windows

 > 

GUI

 > 

malloc induit une boucle infinie


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

malloc induit une boucle infinie

jeudi 15 septembre 2011 à 18:13:43 | malloc induit une boucle infinie

macburn

Bonjour tout le monde !

Pour mon premier message, j'aimerai mettre en évidence un problème assez étrange dont je ne parviens pas a m'extirper...

J'ai créé une application avec une interface graphique QT. Cela fonctionne très bien avec Linux. J'ai essayé de la porter sous Windows, et la patatra...

L'application utilise une librairie externe (.dll) que j'ai donc créée avec Cygwin pour Windows. Lorsque j'appelle une fonction contenue dans cette librairie, la première instruction est une réservation mémoire (malloc). Et la le programme entre en boucle infinie...

J'ai donc essayé un débogage pas-a-pas en assembleur, et l’implémentation du malloc semble responsable. En effet, le programme est multi-threadé, et je ne sais pas si le problème est que le malloc n'est pas "thread-safe", ou si il peut venir d'ailleurs (c'est la première fois que je compile avec Windows).

Vu le déroulement du code, j'ai vraiment l'impression qu'un thread en appelle un autre, puis un autre, jusqu’à revenir au thread de départ, pour recommencer a l'infini...
Ce n'est que mon hypothèse, le problème est peut être ailleurs.

De plus, la librairie externe a été compilée avec Cygwin, alors que l'application finale QT est compilée avec MinGW32. Peut être une incompatibilité...

Merci a ceux qui feront quelques propositions...
vendredi 16 septembre 2011 à 10:57:42 | Re : malloc induit une boucle infinie

CptPingu

Administrateur CodeS-SourceS

Cela fonctionne très bien avec Linux.


Avant d'affirmer cela, plusieurs tests à faire:
- Passe ton programme dans valgrind (memcheck) => Vérifie les leak et les mauvais accès mémoire.
- Passe ton programme dans helgrind => Vérifie les soucis de concurrence.

librairie


Bibliothèque.

le malloc n'est pas "thread-safe"


Le malloc n'a jamais été thread-safe :) Néanmoins, je doute que le problème vienne de malloc, mais plutôt de son utilisation (sous une appli multi-threadé, une erreur de synchronisation peut provoquer des erreurs très loin de la "vraie" erreur).

De plus, la librairie externe a été compilée avec Cygwin, alors que l'application finale QT est compilée avec MinGW32. Peut être une incompatibilité...


Pas sur que cygwin et mingw32 aient des compilateurs à jour, ni qu'ils aient les mêmes versions. As-tu tenté de compiler la bibliothèque externe et le programme principal à l'aide du même compilateur ? (Normalement, tant que l'ABI est compatible, ça ne devrait pas être un soucis, mais c'est toujours une piste à tenter.)

Autre question: Fais-tu des allocations dans la bibliothèque externe ?

________________________________________________________________________
Historique de mes créations, et quelques articles:
http://0217021.free.fr/portfolio
Merci d'utiliser Réponse acceptée si un post répond à votre question
vendredi 16 septembre 2011 à 17:27:32 | Re : malloc induit une boucle infinie

macburn

Merci pour cette réponse.

Je passe le programme dans Valgrind dès mon retour chez moi, c'est vrai que Linux est plus tolérant avec les allocations mémoire "foireuses".

Le malloc n'a jamais été thread-safe :)



Aie. J'ai bien essayé de désactiver le multi-thread, car je n'en ai pas vraiment besoin, mais je me suis dit que peut être était-ce nécessaire pour une appli QT ? De toute façon le retrait de l'option -mthreads dans le Makefile n'a rien donné.

Je vais par ailleurs essayer de tout compiler avec MinGW32 comme suggéré.

Fais-tu des allocations dans la bibliothèque externe ?



Si tu entends par la des allocations dynamiques avec new, non, pas dans la bibliothèque externe, mais certaines sont faites dans le programme principal.
vendredi 16 septembre 2011 à 17:39:42 | Re : malloc induit une boucle infinie

CptPingu

Administrateur CodeS-SourceS

Je passe le programme dans Valgrind dès mon retour chez moi, c'est vrai que Linux est plus tolérant avec les allocations mémoire "foireuses"



Il n'y a pas plus de tolérance d'un côté que de l'autre. Jsute quelques différences internes. L'important est de bien comprendre que tant que tu n'écris pas sur une page non ouverte, il n'y a pas de d'erreur même en cas de dépassement de borne.
(D'où le nom segfault, qui devrait plutôt s'appeler pagefault).
On peut forcer les allocations en fin de page avec la bibliothèque DUMA. (En revanche ne pas mélanger vlagrind et DUMA).

J'ai bien essayé de désactiver le multi-thread, car je n'en ai pas vraiment besoin,


Au vu de cette remarque, quelque chose me dit que tu as des connaissances très superficielles en multi-threading, je me trompe :p ?
En fait, tant que tes données sont locales et qu'il n'y a pas deux threads d'exécution qui veulent accéder à une variable partagée, il n'y a aucun problème. Aucun mutex n'est nécessaire.

Si tu entends par la des allocations dynamiques avec new, non,


Ok, tant mieux.

Si ton programme principal, en dehors de Qt n'est pas trop gros, n'hésite pas à le poster. Il y a peut être une subtilité que tu n'as pas perçu, et qui pourrait être la vraie cause du problème. (C'est du C ou du C++ que tu fais ?).

________________________________________________________________________
Historique de mes créations, et quelques articles:
http://0217021.free.fr/portfolio
Merci d'utiliser Réponse acceptée si un post répond à votre question
vendredi 16 septembre 2011 à 18:18:36 | Re : malloc induit une boucle infinie

macburn

quelque chose me dit que tu as des connaissances très superficielles en multi-threading



Bien vu ! Mais comme j'utilise quelques objets QT, je me suis dit que ceux-ci nécessitaient peut être l'utilisation de threads, étant donné que je n'ai aucune idée sur la manière dont ils sont implémentés.

C'est du C ou du C++ que tu fais ?



La bibliothèque est codée en C, mais mon programme est en C++ pour pouvoir utiliser les objets QT.

Je vais voir s'il est intéressant de poster mon programme, ou du moins la fonction qui pose problème. De toute façon elle n'est pas très longue, ça devrait pouvoir se faire.
dimanche 18 septembre 2011 à 02:53:01 | Re : malloc induit une boucle infinie

macburn

Voilà, désolé pour le retard.
J'ai isolé la partie de code problématique en assembleur. Je ne pense pas que le code C++ soit révélateur de quoi que ce soit concernant ce problème, je me permets donc de poster de l'assembleur (toute mes excuses) !

Donc, ci-dessous l'appel du Malloc par le prog principal :

Code :
0x6a6453d1  <+0x0001>         mov    %esp,%ebp
0x6a6453d3  <+0x0003>         sub    $0x28,%esp
0x6a6453dd  <+0x000d>         mov    %ebx,-0xc(%ebp)
0x6a6453e0  <+0x0010>         mov    %esi,-0x8(%ebp)
0x6a6453e3  <+0x0013>         mov    0xc(%ebp),%esi
0x6a6453e6  <+0x0016>         mov    %edi,-0x4(%ebp)
0x6a6453e9  <+0x0019>         mov    0x10(%ebp),%edi
0x6a6453d6  <+0x0006>         movl   $0xd0,(%esp)
0x6a6453ec  <+0x001c>         call   0x6a646b90 (malloc)
0x6a6453f3  <+0x0023>         mov    %eax,%ebx


Le problème apparaît donc un peu plus loin, dans l'implémentation du malloc :

Code :
0x610c34f9          push   %ebx
0x610c34fa  <+0x0001>         push   %edx
0x610c34fb  <+0x0002>         mov    %fs:0x4,%ebx
0x610c3502  <+0x0009>         mov    $0x1,%eax
0x610c3507  <+0x000e>         xchg   %eax,-0x24d8(%ebx)
0x610c350d  <+0x0014>         mov    %eax,-0x24dc(%ebx)
0x610c3513  <+0x001a>         test   %eax,%eax
0x610c3515  <+0x001c>         je     0x610c351e <_sigfe+37>
0x610c3517  <+0x001e>         call   0x61077680 (yield)
0x610c351c  <+0x0023>         jmp    0x610c3502 <_sigfe+9>
0x610c351e  <+0x0025>         mov    $0x4,%eax
0x610c3523  <+0x002a>         xadd   %eax,-0x24d4(%ebx)
0x610c352a  <+0x0031>         lea    0x610c3545,%edx
0x610c3530  <+0x0037>         xchg   %edx,0xc(%esp)
0x610c3534  <+0x003b>         mov    %edx,(%eax)
0x610c3536  <+0x003d>         incl   -0x24e0(%ebx)
0x610c353c  <+0x0043>         decl   -0x24d8(%ebx)
0x610c3542  <+0x0049>         pop    %edx
0x610c3543  <+0x004a>         pop    %ebx
0x610c3544  <+0x004b>         ret


Et c'est ici que tout se complique, l'instruction #10 (le jump) est exécutée en boucle ! Le test (ligne #7) se révèle faux à chaque passage. Et l'appel de "yield" ne donne rien. Je vous mets le code de "yield" ci-dessous pour information :

Code :
0x61077680          sub    $0xc,%esp
0x61077683  <+0x0003>         call   0x61159f38 (SwitchToThread@0)
0x61077688  <+0x0008>         call   0x61159f38 (SwitchToThread@0)
0x6107768d  <+0x000d>         add    $0xc,%esp
0x61077690  <+0x0010>         jmp    0x61159f38 (SwitchToThread@0)
0x61077695  <+0x0015>         lea    0x0(%esi,%eiz,1),%esi
0x61077699  <+0x0019>         lea    0x0(%edi,%eiz,1),%edi


Ici, les appels au thread@0 sont un peu étranges...

J'imagine que tout ça est un peu rébarbatif, mais si un courageux a une option, je lui serais vraiment reconnaissant de la proposer.

Et encore une fois, ceci n'est peut être qu'un symptôme d'un problème situé ailleurs...
dimanche 18 septembre 2011 à 13:55:42 | Re : malloc induit une boucle infinie

CptPingu

Administrateur CodeS-SourceS
Je ne pense pas que regarder le code de malloc en assembleur t'aidera. Si malloc était buggé, ça se saurait depuis le temps...

L'erreur est induite par une erreur en amont. Il suffit d'avoir une erreur mémoire ou une erreur de synchronisation pour immédiatement obtenir un comportement indéterminé.

Que donne un passage de valgrind ? De helgrind ? De DUMA ?

Peux-tu poster ton code C ?

________________________________________________________________________
Historique de mes créations, et quelques articles:
http://0217021.free.fr/portfolio
Merci d'utiliser Réponse acceptée si un post répond à votre question
dimanche 18 septembre 2011 à 16:59:02 | Re : malloc induit une boucle infinie

macburn

Effectivement il y a un gros problème, Valgrind me renvoie un nombre incalculable d'erreurs de ce genre :

Code :
4,080 bytes in 1 blocks are possibly lost in loss record 5,805 of 5,874
==4617==    at 0x4C27870: memalign (vg_replace_malloc.c:581)
==4617==    by 0x4C278C9: posix_memalign (vg_replace_malloc.c:709)
==4617==    by 0x737233B: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.2800.6)
==4617==    by 0x7373860: g_slice_alloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.2800.6)
==4617==    by 0x7CE4186: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0x7CE4238: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0x7D05A6A: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0x7D08361: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0x7D0C17F: g_type_add_interface_static (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0xE3C9C65: atk_no_op_object_get_type (in /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.9.1)
==4617==    by 0xE3C9C8D: atk_no_op_object_new (in /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.9.1)
==4617==    by 0xD706C8D: ??? (in /usr/lib/libgtk-x11-2.0.so.0.2400.4)
==4617== 
==4617== 4,080 bytes in 1 blocks are possibly lost in loss record 5,806 of 5,874
==4617==    at 0x4C27870: memalign (vg_replace_malloc.c:581)
==4617==    by 0x4C278C9: posix_memalign (vg_replace_malloc.c:709)
==4617==    by 0x737233B: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.2800.6)
==4617==    by 0x7373860: g_slice_alloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.2800.6)
==4617==    by 0x7373915: g_slice_alloc0 (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.2800.6)
==4617==    by 0x7D0C398: g_type_create_instance (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0x7CEA76B: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0x7CED388: g_object_newv (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0x7CEE320: g_object_new_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0x7CEE620: g_object_new (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.2800.6)
==4617==    by 0x5375FD9: ??? (in /usr/lib/libQtGui.so.4.7.2)


Leur quantité est proportionnelle au temps d'exécution du programme.
Je vous mets mon code C++. D'abord, le constructeur de la fenêtre :

Code C/C++ :
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    /***************************************************************************** on charge la liste ****/
    liste = new QComboBox();
    liste->setParent(this);
    liste->setGeometry(20,20,350,30);
    liste->setEnabled(true);
    liste->addItem(QString("fichiers disponibles"));

    struct dirent *lecture;
        
	DIR *rep;
        rep = opendir("./files" );
        while ((lecture = readdir(rep))) {
            std::string ext = lecture->d_name;

            if(ext != "." && ext != "..")
                if(strcmp(ext.substr((int)strlen(ext.c_str())-3,3).c_str(),"url") == 0)
                    liste->addItem(QString(get_string(lecture->d_name)));
        }
        closedir(rep);

    liste->show();

    /***************************************************************************** on charge la zone texte ****/
    infos = new QTextEdit();
    infos->setParent(this);
    infos->setGeometry(20,60,350,180);
    infos->setText(QString(get_string("Liste chargée.")));
    infos->show();

    /***************************************************************************** on charge le bouton ****/
    press = new QPushButton();
    press->setParent(this);
    press->setGeometry(20,250,70,30);
    press->setText(QString(get_string("Charger")));
    press->show();

    stop = new QPushButton();
    stop->setParent(this);
    stop->setGeometry(20,250,70,30);
    stop->setText(QString(get_string("Stop")));
    stop->hide();


    /***************************************************************************** on charge la barre ****/
    barre = new QProgressBar();
    barre->setParent(this);
    barre->setGeometry(100,250,270,30);
    barre->setValue(0);
    barre->show();

    /***************************************************************************** déclarations signaux/slots ****/
    connect(press, SIGNAL(clicked()), this, SLOT(s_clicked()));
    connect(stop, SIGNAL(clicked()), this, SLOT(stop_clicked()));
    connect(liste,SIGNAL(currentIndexChanged(QString)), this, SLOT(s_liste_select(QString)));
    selectedProgram = new QString("");
    statut = false;
    bar_value = 0;

}


Et le slot où apparaît le problème lorsque l'on clique sur le bouton "Charger". Il essaye de se connecter au flux mms, et entre en boucle infinie. Je précise que la toute première instruction de la fonction mmsx_connect() est le malloc en question.

Code C/C++ :
void MainWindow::s_clicked()
{
    statut = true;
    press->hide(); //bouton
    stop->show();  //bouton
    infos->setText(QString(get_string("Etablissement de la connexion...")));
    this->update();
    this->repaint();


    // la boucle infinie apparaît lors de l'appel de la fonction mmsx_connect()
    mmsx_t * tmp = mmsx_connect(0, 0, "mms://site.com/video.wmv", 8*1024*300);
    
    if( inst == NULL )
    {
        QMessageBox message(QMessageBox::Information, "alerte", "connexion échouée");
        message.exec();
        std::cout << "Erreur lors de la connexion au flux." <<std::endl;
        return;
    }
}

Il y a d'autres instructions après le test if(), mais comme elles ne sont jamais exécutées je ne les ai pas inclues pour que ce soit plus léger à lire.


En espérant que ça aide !
dimanche 18 septembre 2011 à 17:08:34 | Re : malloc induit une boucle infinie

CptPingu

Administrateur CodeS-SourceS
Je peux surement t'aider mais je n'ai besoin que d'une seule chose: Le code C, en dehors de Qt.
Si tu me le postes, je pourrais le tester sur ma machine, et peut être voir le potentiel souci.
(Avant d'embarquer ton code dans Qt, il faut déjà tester le module C tout seul dans valgrind).

________________________________________________________________________
Historique de mes créations, et quelques articles:
http://0217021.free.fr/portfolio
Merci d'utiliser Réponse acceptée si un post répond à votre question
dimanche 18 septembre 2011 à 18:11:16 | Re : malloc induit une boucle infinie

macburn

Le code sans QT est le suivant :

Code C/C++ :
#include <libmms/mmsx.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <sys/types.h>
#include <dirent.h>
#include <math.h>
#include <time.h>
#include <sstream>

int main()
{

	float bar_value = 0;
	mmsx_t * inst =  mmsx_connect(NULL, NULL, "mms://a988.v101995.c10199.e.vm.akamaistream.net/7/988/10199/3f97c7e6/ftvigrp.download.akamai.com/10199/cappuccino/production/publication/Autre/Autre/2011/S37/J5/313308_desparolesetdesactes_20110915.wmv", 8*1024*300);

    if( inst == NULL )
    {
            std::cout << "Erreur lors de la connexion au flux." <<std::endl;
            return 1;
    }

    std::cout << "Maintenant connecté." << std::endl;

    FILE * pFile;
    pFile = fopen ("file.wmv","w");
    if (pFile==NULL)
    {
            std::cout << "Erreur lors de la création du nouveau fichier." <<std::endl;
            return 1;
    }


    int remaining =  mmsx_get_length(inst) - mmsx_get_current_pos(inst);
    int remaining_old = mmsx_get_length(inst);
    int ret;
    char * data = new char[1024];

    while(bar_value<100)
    {
            ret = mmsx_read(0, inst, data, 1024);

            if(ret < 0)
            {
                    std::cout << "Le fichier a été trouvé mais ne peut être lu." << std::endl;
                    return 1;
            }


            fwrite (data , 1 , 1024 , pFile );

            bar_value = ((float)(mmsx_get_length(inst) - remaining)/mmsx_get_length(inst)*100);
            int total = mmsx_get_length(inst);
            int parcouru = mmsx_get_current_pos(inst);

            // créer un flux de sortie
                std::ostringstream oss1;
                std::ostringstream oss2;
             // écrire un nombre dans le flux
                oss1 << total/(1024*1024);
                oss2 << parcouru/(1024*1024);
             // récupérer une chaîne de caractères
                std::string total2 = oss1.str();
                std::string parcouru2 = oss2.str();

            remaining_old = remaining;
            remaining = mmsx_get_length(inst) - mmsx_get_current_pos(inst);

    }

    delete [] data;

    mmsx_close (inst);
    std::cout << "Connexion terminée." << std::endl;
    fclose (pFile);

    return 0;
}



Vous aurez peut être besoin de la bibliothèque libmms disponible à cette adresse : libmms

1 2

Cette discussion est classée dans : problème, boucle, application, infinie, malloc


Répondre à ce message

Sujets en rapport avec ce message

Boucle infinie sans aucune raison apparente... [ par madcow41 ] Bonjour,Dans mon projet de C, je doit traiter un fichier Log d'un site.Seul problème, lors du traitement, mon programme se bloque, sans aucune raison boucle infinie,enfin presque... [ par booth ] bonjour, je suis semi newbie en C++, et je viens de faire un prog avec des sockets...le truc c'est que je suis obligé d'utiliser une boucle ainfinie p Problème de vues... [ par Kkeyser ] Bonjour,Voilà mon problème : la fenêtre principale de mon application est divisée en 2 vues : une CTreeView et une CView.J'ai donc naturellement utili Calque pour application graphique [ par Grand_steak ] Bonjour, J'aimerai un petit coup de main pour développer mon appli. graphique.Je dessine une courbe contenant un nbre important de point.Jusque là, pa Problème malloc sous RedHat 7.3 [ par deuchman ] Salut à tous !Voilà, j'ai un problème avec un programme C sous une RedHat 7.3.Lorsque j'utilise la fonction mallc pour allouer de la mémoire à un tabl Problème avec une boucle while [ par arconius ] voilà j'ai fait un prog où l'on tire des dés mais j'ai un problème avec ma boucle while car au lieu de me donner un chiffre aléatoire à chaque fois il Problème de boucle dans un muli-thread [ par vinvay ] Alors voila, j'ai 4 threads qui tournent en même temps, ceux-ci utilisant la même fonction.Dans cette fonction, il y a une première boucle for suivie problème avec le port COM dans une application mfc [ par gengis69 ] j'ai une application mfc qui me permet d'envoyer des info sur un port COM, je sélectionne celui-ci dans mon ihm, seul problème, quand le port selectio condition de finitude d une boucle infinie [ par sebby_06200 ] bonjourj ai un soucis et je pense que vous pouvez m aiderj ai besoin d'envoyer une infinité de signaux par l'intermédiaire d un port sérieet il faut q Probleme avec Sleep [ par rasta_raf ] Bonjour,Je voudrais faire en sorte que dans mon application je fais une action (incrémenter une variable par exemple) chaque moitié de seconde par ex


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,045 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales