Segmentation fault sur un tableau de char

Résolu
MaxSoldier Messages postés 289 Date d'inscription dimanche 10 août 2003 Statut Membre Dernière intervention 28 février 2009 - 26 avril 2008 à 22:13
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 - 27 avril 2008 à 20:33
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

SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
27 avril 2008 à 00:47
MTConnectArg* Param;
...
Param->Host = Host;

Où alloues tu la mémoire pour Param ?

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

Voili, voilou !

Digital Guru
0
NairodDorian Messages postés 130 Date d'inscription lundi 26 juin 2006 Statut Membre Dernière intervention 18 août 2008
26 avril 2008 à 23:25
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.
0
MaxSoldier Messages postés 289 Date d'inscription dimanche 10 août 2003 Statut Membre Dernière intervention 28 février 2009 2
27 avril 2008 à 00:03
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=-
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
NairodDorian Messages postés 130 Date d'inscription lundi 26 juin 2006 Statut Membre Dernière intervention 18 août 2008
27 avril 2008 à 00:06
Ton compilo pointe la ligne 119 où est elle?
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
27 avril 2008 à 01:07
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.
0
MaxSoldier Messages postés 289 Date d'inscription dimanche 10 août 2003 Statut Membre Dernière intervention 28 février 2009 2
27 avril 2008 à 13:50
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=-
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
27 avril 2008 à 14:36
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.
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
27 avril 2008 à 16:00
"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++ (@++)<!--
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
27 avril 2008 à 18:18
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??
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
27 avril 2008 à 18:51
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++ (@++)<!--
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
27 avril 2008 à 20:33
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...
0
Rejoignez-nous