Eviter les debordement memoire en c

cs_flofloo Messages postés 45 Date d'inscription samedi 5 juin 2004 Statut Membre Dernière intervention 16 mars 2009 - 6 août 2008 à 11:49
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 - 7 août 2008 à 16:10
bonjour tout le monde j'ai un probleme avec la gestion des pointeurs voila je m'explique de suite...
j'ai une fonction "ExtractString" dont voici l'entete :
char *ExtractString(char *string,int pos,char sep);cette fonction extrait une sous chaine de l'argument "string".le remplisage du pointeur renvoyer par la fonction commence a partir de l'argument pos et continue tant que le caractere lu est different de l'argument sep!
mais voila la sous chaine renvoyee ne prend que 32 caracteres!alors comment empecher le debordement memoire durant le remplisage du pointeur!
gespere m'etre bien expliquer
merci..

11 réponses

Neo_Fr Messages postés 653 Date d'inscription mardi 6 décembre 2005 Statut Membre Dernière intervention 10 novembre 2014 2
6 août 2008 à 12:28
Une string est normalement toujours terminer par le caractere NULL(0), tu as donc juste a controle que le caractere pointé par ton pointeur est positif..
Poste ton code sinon ce sera mieux pour t'aider

Neo_Fr
0
cs_flofloo Messages postés 45 Date d'inscription samedi 5 juin 2004 Statut Membre Dernière intervention 16 mars 2009
6 août 2008 à 15:18
le voici :

void extractstring(char *string,int pos,char sep)
{
     char *extract = malloc(32*sizeof(char));
    int i;i=0;
  char c = string[i];
while(c!=sep)
{
  extract[i] = sep;
}
}
0
cs_flofloo Messages postés 45 Date d'inscription samedi 5 juin 2004 Statut Membre Dernière intervention 16 mars 2009
6 août 2008 à 15:21
mince g fait kelke erreur dsl :
dans le while :
extract[i] = c;//et non sep
i++;
c = string[i];
et si vous pouver m'aider dans l'ecriture avec les pointeur d'une facon plus efficace merci..et dsl encore
0
Neo_Fr Messages postés 653 Date d'inscription mardi 6 décembre 2005 Statut Membre Dernière intervention 10 novembre 2014 2
6 août 2008 à 16:19
Evite tant que possible de retourner de la memoire allouer avec malloc si tu veux pas etre obliger de faire des free() partout dans ton code.., le mieux reste d'écrire directement sur un pointeur passer en param de cette facon tu fait l'alloc/desalloc en dehors de ta fonction ce qui evite tout oublie de desalloc..

Ex:

void __stdcall ExtractString(LPSTR lpszIn, LPSTR lpszOut, DWORD dwStartFrom, char Separator)
{
LPSTR lptr;
lptr = lpszIn + dwStartFrom;
while(*lptr !Separator) *lpszOut++ *lptr++;
*lpszOut = 0;
}

int main(void)
{
char szTest[] = "blablablaCeci est un test;blabla";
char szRet[16];
ExtractString(szTest, szRet, 9, ';');
printf("%s", szRet);

system("PAUSE");
return 0;
}

Neo_Fr
0

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

Posez votre question
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
6 août 2008 à 16:27
void ExtractString(LPSTR lpszIn, LPSTR lpszOut,, UINT uLen, UINT uStartFrom, char cSeparator)

{

    LPSTR lptr;

    // Ici on pourrait tester que les paramètres contiennent les valeurs nécessaires

    lptr = lpszIn + uStartFrom;    while(*lptr && --uLen && *lptr !cSeparator) *lpszOut++ *lptr++;
    *lpszOut = 0;

}

ExtractString(szTest, szRet, sizeof(szRet), 9, ';');

C++ (@++)<!--
0
zaibacker Messages postés 97 Date d'inscription vendredi 17 février 2006 Statut Membre Dernière intervention 24 janvier 2018
6 août 2008 à 16:29
Salut, je te propose ce code que je n'ai pas testé
2 inconvénients:
- dans notre cas nous n'avons alloué que 32 octets(soit 32 caractères au maximum).
- si l'arguments "sep" n'est pas trouvé, je ne veux même pas savoir ce qui va se passer car ile while n'a aucune autre clause d'arret.

void extractstring(char *string,int pos,char sep)
{
char *extract = malloc(32*sizeof(char));
int i;


i= 0;
j = pos;


while( extract[i] != sep )


extract[i] = string[j];


i++;
j++;


}


extract[i] = '\0';
}
PS: je crois que "char *extract malloc(32*sizeof(char));" pourrait être remplacé par "char *extract malloc(strlen(string)*sizeof(char)); "
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
6 août 2008 à 16:33
"- dans notre cas nous n'avons alloué que 32 octets(soit 32 caractères au maximum)."

Là tout l'intérêt du code proposé par neo_fr

"- si l'arguments "sep" n'est pas trouvé, je ne veux même pas savoir ce
qui va se passer car ile while n'a aucune autre clause d'arret."

Là tout l'intérêt du code modifié de neo_fr que j'ai proposé.

C++ (@++)<!--
0
cs_Telepathmaster Messages postés 46 Date d'inscription vendredi 31 octobre 2003 Statut Membre Dernière intervention 7 août 2008
7 août 2008 à 13:34
Pour revenir à la question de l'allocation dynamique, même si pour ce type de fonction il est clair qu'un alloc interne n'est pas la meilleure solution, je donnerais ça pour la posterité et la pédagogie pour les cas où c'est nécessaire :

char * extractString(char * str, size_t pos, char sep) {

    int i;
    char * ext;

    if (pos > strlen(str))
       return NULL;

    /* Rappel au passage qu'un pointeur est passé par valeur */
    str += pos;

    for ( i = 0; i < strlen(str) && str[i] != sep;i++);

    /* Connaissant désormais la taille à allouer on ne risque plus l'overflow */
    ext = malloc(i+1);
    memcpy(ext,str,i);
    ext[i] = 0;

    return ext;

}

int main() {

    char str [] = "da;test;string", * tmp;
   
    if ((tmp = extractString(str,3,';')) != NULL)
        printf("%s\n",tmp);
   
    free(tmp);
   
    return 0;

}

Une autre solution, come cité plus haut serait de systématiquement allouer la taille de la chaine originale, mais dans ce cas l'utilité d'une allocation dynamique devient nulle.
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
7 août 2008 à 14:47
Appel strlen UNE SEULE FOIS avant le test if(pos > strlen(...)). D'ailleurs ici, ça devrait être if(pos >= len).
Puisque que la taille est déjà récupérée, on l'utilisera aussi dans la boucle mais sinon, suffit simplement de tester si le caractère courant (str[i]) est non nul.

"mais dans ce cas l'utilité d'une allocation dynamique devient nulle."

Peut-être mais pour la perte de cycle CPU que cela occasionne, peut-être est-il mieux de ne pas en tenir compte.

C++ (@++)<!--
0
cs_Telepathmaster Messages postés 46 Date d'inscription vendredi 31 octobre 2003 Statut Membre Dernière intervention 7 août 2008
7 août 2008 à 15:13
Tout d'abord, les "oprimisations" du type n'appeller une fonction constante qu'une fois ont rarement un effet positif. Voire des effets négatifs. Pourquoi ? Parce qu'il est incroyable de voir ce que le compilateur fait dans notre dos. Notamment, ce genre de chose est transformée en un seul appel dont la valeur est stockée dans un registre (pas forcément le cas d'une variable déclarée explicitement). Ca dépend des compilateurs, des plateformes, à tel point que ça ne vaut pas la peine d'en parler.

Si on veut chipoter, je dirais qu'un str[i] impose un defer du pointeur et prends un cycle d'horloge de plus qu'une comparaison avec un entier.

Enfin, et *surtout* j'ai écrit rapidement ce bout de code pour permettre à l'auteur du topic d'avoir un exemple d'utilisation de pointeurs et de l'allocation dynamique, sans prétendre qu'il était meilleur ou optimisé. J'ai d'ailleurs précisé que ce n'était pas la meilleure solution. Ceci dit, pour la compréhension il est bon de pouvoir connaitre une ou deux manières de faire. Je rappelle d'ailleurs que beaucoup de librairies ou d'interfaces (SQLite, OpenSSL, ...) utilisent couramment ce genre de techniques.

Quoiqu'il en soit, j'avoue que je passe par ce site assez rarement. Quand je vois un message auquel je peux répondre rapidement et simplement je le fais. Si c'est pour me coltiner des réponses négatives et qui réduisent ma contribution à deux points lambda qui n'ont pas de rapport avec le sujet alors que j'essaie d'apporter un tout petit peut de pédagogie, merci bien...

Cordialement,
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
7 août 2008 à 16:10
"Parce qu'il est incroyable de voir ce que le compilateur fait dans
notre dos. Notamment, ce genre de chose est transformée en un seul
appel dont la valeur est stockée dans un registre (pas forcément le cas
d'une variable déclarée explicitement)."

Pas du tout. La valeur déclaré explicitement a toutes les chances d'être placée directement dans un registre. Un appel à une fonction de ce genre est trop incertain. En effet, rien ne garanti au compilo que la chaine ne sera pas modifiée dans la boucle (explicitement ou avec une fonction). Pour cette raison, un appel à une fonction reste un appel à une fonction ("inliné" dans certains cas mais dont le code est toujours présent.) et doit être considéré ainsi dans le code source aussi.

char buf[300];
int i;

fgets(buf, sizeof(buf), stdin);

for(i = 0; i < strlen(buf); i++)
    printf("%c", buf[i]);

Génère donc un listing de ce code et jette un coup d'oeil au code assembler (optimiser par le compilo bien entendu). Tu me reparleras de tes supposées optimisations automatiques après.

Je remarque une chose bien précis (code généré avec VC++):

$LL9@main:
    mov cl, BYTE PTR [eax]
    inc eax
    test   cl, cl
    jne SHORT $LL9@main

C'est le strlen "inliné".
Et ce code est tout en bas de la boucle et reviendra donc forcément à chaque tour de boucle.

"Si c'est pour me coltiner des réponses négatives et qui réduisent ma
contribution à deux points lambda qui n'ont pas de rapport avec le
sujet alors que j'essaie d'apporter un tout petit peut de pédagogie,
merci bien..."

Je n'essaie pas de réduire pas tes efforts à zéro. J'essaie de les corriger au mieux de mon savoir.
N'oublie pas que les débutants on tendance à tout copier sans se posé de question.

C++ (@++)<!--
0
Rejoignez-nous