[langage c] question (en cours)

Applications multimedia / jeux
Répondre
AchilleFraisse
Elfe
Messages : 618
Inscription : dim. 27 avr. 2014, 09:32

[langage c] question (en cours)

Message par AchilleFraisse »

Bonjour,
On peut poser des questions sur un programme écrit en C sur ce forum ?
Avatar de l’utilisateur
FoolEcho
Maître du Kyudo
Messages : 10707
Inscription : dim. 15 août 2010, 11:48
Localisation : Basse-Normandie

Re: [langage c] question (en cours)

Message par FoolEcho »

Tu peux toujours... après, ce n'est pas la vocation de ce forum, forcément.
«The following statement is not true. The previous statement is true.» :nage:
Avatar de l’utilisateur
ed0c
Chu Ko Nu
Messages : 329
Inscription : mer. 24 mars 2010, 10:02

Re: [langage c] question (en cours)

Message par ed0c »

Moi je dis qu'il ne peut pas
AchilleFraisse
Elfe
Messages : 618
Inscription : dim. 27 avr. 2014, 09:32

Re: [langage c] question (en cours)

Message par AchilleFraisse »

J'ai un programme qui se connecte via la protocole imap sur mon serveur mail.
J'ai une boucle infini (Tant que l'utilisateur ne veut pas quitter en tapant LOGOUT), qui permet d'envoyer des requêtes au serveur mail puis de recevoir les réponses :

Code : Tout sélectionner

/* On boucle tant que l'utilisateur ne veut pas quitter */
while((strstr(msg, "LOGOUT\r\n")) == NULL)
    {
        char *data = ""; /* Chaine contenant la réponses du serveur */

        i++;
        /* Saisie de l'utilisateur */
        printf("\n> ");
        input(tmp, 1024); /* Voire la fonction input comme la fonction scanf, mais en plus évolué */

        sprintf(msg, "%d %s\r\n", i, tmp); /* On construit le message à envoyer au serveur mail */

        /* Envoie de la saisie au serveur */
        if(send(sock, msg, strlen(msg), 0) < 0)
        {
            perror("send()");
            exit(errno);
        }

        /* Récupération des données */
        do {
            /* On recoit les données par bloc de 1024 octets */
            if((n = recv(sock, buffer, sizeof buffer, 0)) < 0)
            {
                perror("recv()");reqûete
                exit(errno);
            }

            /* On termine la chaine de caractère par le '\0' de fin de chaine */
            if(n < 1024)
                buffer[n] = '\0';

            /* VERSION 1 : COMMENTER CETTE LIGNE */
            data = add(data, buffer); /* Reconstruction de la chaine */

            /* On ferme le serveur à la demande de l'utilisateur */
            if((strstr(msg, "LOGOUT\r\n")) != NULL)
            {
                printf("Serveur fermé !\n\n");
                break;
            }
            /* VERSION 1 : DECOMMENTER CES DEUX LIGNES */
            //else
            //   printf("%s", buffer);

        } while(strstr(buffer, "completed.\r\n") == NULL);

	/* VERSION 1 : COMMENTER CETTE LIGNE */
        printf("%s", data);
        
        free(data);
    }
Et voici la fonction add :

Code : Tout sélectionner

char *add(char *ch1, char *ch2)
{
    char *data = "";
    int i, j, n = strlen(ch1), m = strlen(ch2);

    data = (char*) malloc(n * sizeof(char) + m * sizeof(char));
    //strcat(data, ch1);
    //strcat(data, ch2);

    for(i = 0 ; i < n ; i++)
        data[i] = ch1[i];

    for(j = i ; j < m+n ; j++)  
        data[j] = ch2[j-i];

    return data; 
}
Les données sont reçu du serveur par bloc de 1024 octets. Ma variable data a donc une taille de 1025 pour accueil le '\0' de fin de chaine.

Lors de la première requête effectué sur le serveur, tout ce passe bien (je reçois bien les données).
Lors de la deuxième requête, je reçois que la moitié des données, et il y a des caractères qui se sont transformé en caractère bizarre. Pourtant les deux requêtes sont identiques.

Je ne vois pas pourquoi ? Voyez vous une erreur dans mon code ?

NB : Je tient à signaler que si je ne regroupe pas toutes les données reçu dans la variable data avant de les afficher, mais que je les affiche par bloc de 1024 octets (décommenter les deux lignes avec le else, et commenter la ligne du printf("%s", data) et data = add() ), tout marche très bien.
Mais ce que je veux c'est toutes mes données d'une requête dans une seule variable.

J'espère avoir été clair.
oktoberfest
Maître du Kyudo
Messages : 1855
Inscription : mer. 06 janv. 2010, 13:51
Localisation : Ried - Alsace - France

Re: [langage c] question (en cours)

Message par oktoberfest »

J'imagine que buffer est déclaré comme ça :

Code : Tout sélectionner

char buffer[1024];
Premier souci : si tu reçois précisément 1024 caractères, tu n'auras pas de '\0' de fin de chaîne à la fin de buffer. Donc ta fonction add ne va pas trop bien marcher.

Ensuite tu as des fuites mémoire, quand tu fais :

Code : Tout sélectionner

data = add(data, buffer)
data pointe sur une zone mémoire. A la sortie de la fonction add, data pointe sur une autre zone mémoire (celle allouée dans add). Mais l'ancienne zone mémoire n'est pas libérée.

PS : Je ne me souvenais plus que le C pouvait être aussi bas niveau et moche à lire :)
La majorité des bugs se situe entre la chaise et le clavier...
Arrêtez de vous prendre la tête avec les partitions... passez au LVM
Avatar de l’utilisateur
benjarobin
Maître du Kyudo
Messages : 17187
Inscription : sam. 30 mai 2009, 15:48
Localisation : Lyon

Re: [langage c] question (en cours)

Message par benjarobin »

Ta fonction add ne réserve pas via le malloc le \0 de fin.
Sinon pourquoi ne pas utiliser strcpy et strcat ? Voir encore plus simple de remplacer toute cette fonction (ok c'est un peu moins rapide mais vraiment tu n'est pas à quelques us prêt) par

Code : Tout sélectionner

asprintf(&data, "%s%s", ch1, ch2)
Zsh | KDE | PC fixe : core i7, carte nvidia
Titre d'un sujet : [Thème] Sujet (état) / Règles du forum
AchilleFraisse
Elfe
Messages : 618
Inscription : dim. 27 avr. 2014, 09:32

Re: [langage c] question (en cours)

Message par AchilleFraisse »

oktoberfest a écrit :J'imagine que buffer est déclaré comme ça :

Code : Tout sélectionner

char buffer[1024];
Premier souci : si tu reçois précisément 1024 caractères, tu n'auras pas de '\0' de fin de chaîne à la fin de buffer. Donc ta fonction add ne va pas trop bien marcher.
Non, justement buffer est déclaré comme ceci :

Code : Tout sélectionner

char buffer[1025];
benjarobin a écrit :Ta fonction add ne réserve pas via le malloc le \0 de fin.
Sinon pourquoi ne pas utiliser strcpy et strcat ? Voir encore plus simple de remplacer toute cette fonction (ok c'est un peu moins rapide mais vraiment tu n'est pas à quelques us prêt) par

Code : Tout sélectionner

asprintf(&data, "%s%s", ch1, ch2)
Je ne connaissais pas asprintf() . Mais lorsque je marque :

Code : Tout sélectionner

asprintf(&data, "%s%s", data, buffer)
il me dit implicit declaration of function asprintf.

Deplus, si je garde mon code précédent et que j’enlève tout simplement free(data), ca marche.
aminnairi
archer de cavalerie
Messages : 187
Inscription : lun. 10 août 2015, 13:50
Localisation : France

Re: [langage c] question (en cours)

Message par aminnairi »

Salut,
AchilleFraisse a écrit : il me dit implicit declaration of function asprintf.

Code : Tout sélectionner

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
[...]
asprintf(3) - Linux man page

*flies away*
Arch Linux x86_64 UEFI
7,3 Gio RAM
Intel® Core™ i5-4200U CPU @ 1.60GHz × 4
Intel® Haswell Mobile + NVIDIA GeForce 840M 2 Gio vRAM
KDE Plasma + SDDM
AchilleFraisse
Elfe
Messages : 618
Inscription : dim. 27 avr. 2014, 09:32

Re: [langage c] question (en cours)

Message par AchilleFraisse »

Il me renvoie encore le même warning
Avatar de l’utilisateur
benjarobin
Maître du Kyudo
Messages : 17187
Inscription : sam. 30 mai 2009, 15:48
Localisation : Lyon

Re: [langage c] question (en cours)

Message par benjarobin »

Pourtant ceci compile (et fonctionne) sans warning

Code : Tout sélectionner

#define _GNU_SOURCE 1
#include <stdio.h>

int main(void)
{
    char *data = NULL;
    const char *ch1 = "hello";
    const char *ch2 = " world";

    asprintf(&data, "%s%s", ch1, ch2);
    puts(data);
    return 0;
}
Compilé avec

Code : Tout sélectionner

gcc -std=c99 -O2 -Wall -Wextra t.c -o t
Zsh | KDE | PC fixe : core i7, carte nvidia
Titre d'un sujet : [Thème] Sujet (état) / Règles du forum
aminnairi
archer de cavalerie
Messages : 187
Inscription : lun. 10 août 2015, 13:50
Localisation : France

Re: [langage c] question (en cours)

Message par aminnairi »

Je confirme, même sans spécifier la version. Donnes-nous la commande que tu utilise pour compiler.
Arch Linux x86_64 UEFI
7,3 Gio RAM
Intel® Core™ i5-4200U CPU @ 1.60GHz × 4
Intel® Haswell Mobile + NVIDIA GeForce 840M 2 Gio vRAM
KDE Plasma + SDDM
Répondre