2011-04-28 2 views
0

J'essaie de copier deux entiers et une chaîne de caractères dans un tampon et d'imprimer les éléments du tampon. Je reçois un défaut seg pour la troisième déclaration printf:Copier une chaîne de caractères dans un tampon non signé: Erreur de segmentation

id = 102; 
    len = 3; 
    str = "working"; 
    memmove(buffer,&message_id,sizeof(id)); 
    memmove(buffer+(sizeof(id)),&len,sizeof(len)); 
    memmove(buffer+(2*sizeof(id)),&string, sizeof(str)); 

    printf("1 is: %d\n", buffer[0]); 
    printf("2 is: %d\n", buffer[4]); 
    printf("3 is %s\n, buffer[8])); // here is where i get the seg fault should 
    be a string 
    /***/ 
    bufer is declared as unsinged char buffer[444]; 

Je ne sais pas pourquoi cela se verrait faute?

+0

ce qui est tampon avec deux "f" déclarés comme - vous dites bufer est unsigned char [444] – Hogan

+0

Comment * string * et * str * déclarés? – karlphillip

Répondre

1

Il y avait plusieurs problèmes sur votre code, mais le point le plus important est que memmove() ne copie pas l'octet de caractère nul de la chaîne.

The function ne vérifie aucun caractère nul dans la source - il copie toujours exactement les octets.

Cela vous donne deux options:

  • compte pour que si vous copiez les choses:

memmove(buffer+sizeof(id)+sizeof(len), str, strlen(str) +1);

  • Ou après que la mémoire a été copiée, assurez-vous la chaîne se termine par '\0' (alias.0) sur votre tampon:

memmove(buffer+sizeof(id)+sizeof(len), str, strlen(str));

buffer[sizeof(id)+ sizeof(len) + strlen(str) + 1] = 0;

Quoi qu'il en soit, le code fonctionne maintenant. Un autre problème était que vous essayiez de spécifier la longueur de la chaîne avec sizeof(str). C'est faux, et vous devriez faire strlen(str). Une dernière chose, pour des raisons de clarté et de sécurité, ne faites pas 2*sizeof(id). Si plus tard vous décidez de changer le type de variable, vous êtes vissé. La bonne façon serait sizeof(id)+sizeof(len). C'est tout.

int id = 102; 
int len = 3; 
char* str = "working"; 
char buffer[444]; 

memmove(buffer,&id,sizeof(id)); 
memmove(buffer+(sizeof(id)), &len, sizeof(len)); 
memmove(buffer+sizeof(id)+sizeof(len), str, strlen(str)); 
buffer[sizeof(id)+ sizeof(len) + strlen(str) + 1] = 0; 

printf("1 is: %d\n", buffer[0]); 
printf("2 is: %d\n", buffer[4]); 
printf("3 is: %s\n", &buffer[8]); 
+0

bonne explication. Merci beaucoup. j'ai oublié d'utiliser strlen et compte pour le caractère nul – Warz

4

buffer[8] est un char, %s attend chaîne, ce qui signifie char *, passer &buffer[8] à la place. Vous obtenez une erreur de segmentation parce que printf essaie de traiter un omble comme pointeur char, qui est l'adresse (et si char est adopté, il est peu probable d'être valide)

EDIT: comme David a commenté , si le point de départ pour copier la chaîne est liée aux valeurs avant, ne pas utiliser une valeur fixe, au lieu de &buffer[8] utilisation buffer+(2*sizeof(id)) ou buffer[2*sizeof(id)]

+0

+1, bien que 'buffer + 8' ou mieux encore' buffer + 2 * sizeof (int) 'serait préférable –

+0

@David - vous avez raison, merci pour le commentaire. – MByD

1

le principal problème est que vous essayez d'imprimer la chaîne en passant seulement un personnage. Cela est dû au fait que buffer[8] fait référence à char à l'index 8, et non à la chaîne commençant à cette position. Donc, vous devez prendre l'adresse de buffer[8] pour en faire une chaîne ou char*.

La raison pour laquelle segfaults est que printf tente d'imprimer une chaîne commençant à l'adresse donnée par le premier caractère (c'est-à-dire le contenu de la chaîne lui-même), qui n'est pas un pointeur valide.

Il existe également un certain nombre de fautes de frappe et d'erreurs. Une version de travail est inférieure à:

#include <stdio.h> 
#include <memory.h> 

int main() 
{ 
    unsigned char buffer[444]; 
    int id = 102; 
    int len = 3; 
    char* str = "working"; 

    memmove(buffer,&id,sizeof(id)); 
    memmove(buffer+(sizeof(id)),&len,sizeof(len)); 
    memmove(buffer+(2*sizeof(id)), str, sizeof(str)); 

    printf("1 is: %d\n", buffer[0]); 
    printf("2 is: %d\n", buffer[4]); 
    printf("3 is %s\n", &buffer[8]); 

    return 0; 
} 

Si vous avez compilé cette application avec tous les avertissements activé, votre compilateur (au moins GCC ne) devrait vous avertir de votre erreur comme celui-ci (c.-à--Wall.):

problem.c:18: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’ 

Les avertissements ne doivent pas être ignorés!

Questions connexes