Segmentation fault sur un tableau de char [Résolu]

Signaler
Messages postés
289
Date d'inscription
dimanche 10 août 2003
Statut
Membre
Dernière intervention
28 février 2009
-
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
-
Bonsoir tout le monde !
Je me suis mis au C/C++ sous linux il y a quelques jours et j'ai de nombreuses erreur de dépassement de tampon (segmentation fault).

Voici mon code complet, c'est un scanneur de port multithreaded qui me sert de test pour voir si je suis capable de coder un programme gérant socket et multithreading (humm !). Mais le problème ne se situe pas sur ces difficultés !

<hr size="2" width="100%" />#include <stdio.h>
#include <stdlib.h>

#include
#include <fcntl.h>

#include

#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <netdb.h>

#include

typedef struct MTConnectArg
{
    char* Host;
    int Port;
};

const int DebugMode = 1;

void* Connect(void* thrArg)
{
    MTConnectArg* Param = (MTConnectArg*)thrArg;

    // variables necessaires au TimeOut
    struct timeval TV;
    fd_set myset;

    if(DebugMode == 1) cout << "### Debug - Initialisation de la connexion..." << endl;

    // Création du socket
    int SktDesc = socket(AF_INET, SOCK_STREAM, 0);

    if(DebugMode == 1) cout << "### Debug - Resolve de l'adresse..." << endl;
   
    // Variable gérant l'adressage et le resolve du nom de domaine
       struct sockaddr_in SktIn;
       struct hostent *ResolvedHost = gethostbyname(Param->Host);

    if(DebugMode == 1) cout << "### Debug - Configuration du socket..." << endl;

    long Arg= 0;

    // Mise en place d'un socket non blocant
    Arg = fcntl(SktDesc, F_GETFL, NULL);
      Arg |= O_NONBLOCK;
      fcntl(SktDesc, F_SETFL, Arg);

    // On set les paramètres du socket
    memset(&SktIn, 0, sizeof(SktIn));
       memcpy((char *) &SktIn.sin_addr.s_addr, ResolvedHost->h_addr_list[0], ResolvedHost->h_length);

       SktIn.sin_family = AF_INET;
       SktIn.sin_port = htons(Param->Port);

    if(DebugMode == 1) cout << "### Debug - Connexion..." << endl;

    int SktRet = connect(SktDesc, (struct sockaddr *)&SktIn, sizeof(SktIn));

       if (SktRet < 0)
         {
            // Vérification du TimeOut
                TV.tv_sec = 1;
                TV.tv_usec = 0;
                FD_ZERO(&myset);
                FD_SET(SktDesc, &myset);
 
                if (select(SktDesc+1, NULL, &myset, NULL, &TV) <= 0)
            {
                cout << "### Debug - TimeOut..." << endl;
            }
            else
            {
                cout << "Open port : " << Param->Port << " !";
                if(DebugMode == 1) cout << "### Debug - Connexion réussie..." << endl;
                if(DebugMode == 1) cout << "### Debug - Fermeture du socket..." << endl;
           
                close(SktDesc);
            }
         }
    else
    {
        if(DebugMode == 1) cout << "### Debug - Connexion échouée..." << endl;
    }

}

int main(int argc, char* argv[])
{
    char Host[256];

    int StartPort = 0;
    int EndPort = 0;
   
    int ThreadLimit = 0;

    MTConnectArg* Param;

    cout << "DGSCan Port Scanner...\nMultithreaded !\n\n";

    cout << "Thread Limit : ";
    cin >> ThreadLimit;

    pthread_t* thrList = (pthread_t*)malloc(sizeof(pthread_t) * ThreadLimit);

    cout << "Host : ";
    cin >> Host;

    cout << "Start port :";
    cin >> StartPort;

    cout << "End port :";
    cin >> EndPort;

    Param->Host = Host;

    cout << "\nDébut du scan sur " << Host << " ..." << endl;

    for(int i = StartPort; i < EndPort; i+= ThreadLimit)
    {
        cout << "Analyse du port "<< i << " ...";

        for(int j = 0; j < ThreadLimit; j++)
        {
            cout << "### Debug - Création du lot de thread..." << endl;
            Param->Port = i + j;

            if(j < EndPort - StartPort)
            {
                cout << "### Debug - Création du thread..." << endl;
                pthread_create(&thrList[j], NULL, Connect, (void*)Param);
            }
        }
    }

return 0;
}
<hr size="2" width="100%" />
Je vous met aussi le dump GDB si ca peut vous aider :

<hr size="2" width="100%" />Starting program: /home/digitalguru/Bureau/Developpement/DGScan V2/DGScanV2
[Thread debugging using libthread_db enabled]
DGSCan Port Scanner...
Multithreaded !

Thread Limit : 10
Host : google.fr
Start port :1
End port :100
[New Thread 0x7f81f35986f0 (LWP 6549)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f81f35986f0 (LWP 6549)]
0x000000000040111e in main (argc=1, argv=0x7ffffb5aea18) at main.c:119
119             Param->Host = (char*)malloc(sizeof(char) * strlen(Host));
Current language:  auto; currently c++
<hr size="2" width="100%" />
Voilà, si quelqu'un a une idée de comment m'en sortir !
Sinon, soyez indulgent sur mon "style" qui doit probablement être assez dégueulasse, car je viens d'une multitude de langage et je ne suis pas très habitué ni aux pointeurs, ni au standart d'écriture du C++.
Je prend bien sûr toutes les remarques

Tchou ! Et merci d'avance !

-=Digital Guru=-

12 réponses

Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
12
MTConnectArg* Param;
...
Param->Host = Host;

Où alloues tu la mémoire pour Param ?

C++ (@++)<!--
Messages postés
289
Date d'inscription
dimanche 10 août 2003
Statut
Membre
Dernière intervention
28 février 2009
2
Ah oui j'ai oublié, pour la compile, j'utilise :
g++  main.c -o DGScanV2 -l pthread -Wno-deprecated -g

Voili, voilou !

Digital Guru
Messages postés
130
Date d'inscription
lundi 26 juin 2006
Statut
Membre
Dernière intervention
18 août 2008

Alors :
pthread_t* thrList = (pthread_t*)malloc(sizeof(pthread_t) * ThreadLimit);

Allocation, où est la Désallocation???
free(thrList); doit se mettre avec return 0 par exemple.

pthread_create(&thrList[j], NULL, Connect, (void*)Param);

Il doit surement comme avec l'api Windows une fonction à appeler du genre pthread_close à vérifier.

if(DebugMode == 1) cout << "### Debug - Connexion échouée..." << endl;

rajoute après ça :
close(SktDesc); !!! A VERIFIER car je ne suis pas habituer au fonction Linux.
Lit la doc de la fonction afin d'être sûr.

Voilà au premier coups d'oeil.
Messages postés
289
Date d'inscription
dimanche 10 août 2003
Statut
Membre
Dernière intervention
28 février 2009
2
Salut !
D'abord, merci à toi d'avoir répondu !

-Pour le free, en effet, petit (gros ?) oubli de ma part !
- Il n'y a pas de fonction pour cloturer un thread, il se ferme tout seul après son execution.
- Pas besoin du close, puisque le socket n'est pas ouvert.

Mais malgrès le free, toujours ce BufferOverflow (je m'y attendais en même temps !) !
Une autre idée ?

Tchou !
-=Digital Guru=-
Messages postés
130
Date d'inscription
lundi 26 juin 2006
Statut
Membre
Dernière intervention
18 août 2008

Ton compilo pointe la ligne 119 où est elle?
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
Au niveau de la propreté :

* headers : choisis iostream ou stdio mais pas les deux, strictement inutile

*
 typedef struct MTConnectArg
{
    char* Host;
    int Port;
};

le typedef ne sert à rien dans ce cas

* tu mélanges cout (librairie C++) avec des struct sockaddr_in par exemple (syntaxe C). Point de vue personnel peut-être, mais je trouve pas ça génial. Choisis un langage et restes-y.
Messages postés
289
Date d'inscription
dimanche 10 août 2003
Statut
Membre
Dernière intervention
28 février 2009
2
Nickel ! Merci SAKingdom, c'était bien ça, encore une erreur toute conne !

Quant aux remarques de Juju, autant pour les includes, j'ai oublié de les enlever lorsque que j'ai changé mes printf en cout, autant, le mélange des sockaddr_in et des cout ne me choquent pas plus que ça !

Mais j'essaierai de faire attention !
Merci encore !
Bye !

-=DigitalGuru=-
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
c'est pas l'utilisation des sockaddr_in qui me gênent, c'est le fait d'utiliser la syntaxe :
struct [type] var;
alors qu'en C++ c'est simplement
[type] var;

l'utilisation de cout montre que forcément tu es en C++ (surcharge de <<, templates, etc...) donc il faudrait utiliser la syntaxe adéquate.
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
12
"il faudrait utiliser la syntaxe adéquate."

Ça, ça dépend vraiment des points de vue. En C++ (surtout), ajouter struct devant nous indique clairement que l'on travail avec une structure et non une classe ou un typedef quelconque (HANDLE et autres).

C++ (@++)<!--
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
moui j'ai dit que c'était un point de vue...
de toutes manières la seule différence entre struct et class c'est l'accès public/private par défaut alors...


quant au typedef que veux-tu dire? un handle c'est jamais qu'un pointeur??
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
12
struct UneChose {
};

class UneChose {
};

typedef int UneChose;

UneChose bidule;

À partir du nom, peut-on dire, au premier coup d'oeil, qu'il s'agit d'une classe, d'une structure ou d'un int ?

Mettre struct devant a, au moins, le mérite d'identifier clairement sur quelle type de donnée on travail (si non spécifié dans le nom ex: CUneChose -> classe).

"de toutes manières la seule différence entre struct et class c'est l'accès public/private par défaut alors..."
Initialement, NON pas du tout.
Malheureusement, en C++, ils ont eu la non-brillante idée de transformer une structure en classe.
Une structure qui pouvait être utilisée pour stocker convenable et clairement des données peut maintenant contenir constructeurs fonctions et tout un barda inutile qui n'a sa place que dans une classe.
Les structures, qui avait une fonction bien précise, peuvent, maintenant, être transformé en un vague objet, un truc de plus pour mélanger les programmeurs.

C++ (@++)<!--
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
Pour ma part j'utilise effectivement des préfixes pour les variables;
remarquons quand même que si tu vois une structure utilisée dans un code, y aura forcément un accès aux membres donc en voyant machin.truc ou pMachin->truc tu pourras d'office pas le confondre avec un typedef sur type natif...
Après en ce qui concerne la différence struct/class...entièrement d'accord avec toi mais le fait est que les struct et les class sont équivalents alors vaut mieux jeter un coup d'oeil sur la définition à chaque fois pour vérifier si présence de constructeur ou autre chose...