2014-06-24 1 views
0

Je reçois une erreur de segmentation lorsque j'utilise strncpy et je n'arrive pas à résoudre le problème.Je ne comprends pas pourquoi je reçois une erreur de segmentation due à strncpy

Voici mon fichier rectangle.h. Ceci est juste un fichier d'en-tête. Il s'agit de mon fichier rectangle.c. Je vais juste en montrer une fonction:

/* create_rectangle alloue dynamiquement de la mémoire pour stocker un rectangle, lui donne * valeurs initiales, et renvoie un pointeur vers le rectangle nouvellement créé. */

struct rectangle *create_rectangle(struct point ul, struct point lr, 
            char *label) { 

    struct rectangle *r = malloc(sizeof(struct rectangle)); 
    /* TASK 1: fill in the rest of this function */ 
    r->upperleft = ul; 
    r->lowerright = lr; 
    r->label = malloc(strlen(label) * sizeof(char)); 
    strncpy(r->label, label, strlen(label) + 1); 

    return r; 
} 

Dans le code ci-dessus, j'utilise malloc d'allouer suffisamment d'espace pour le pointeur d'étiquette.

Lorsque j'exécute le programme tester.c ci-dessous, j'obtiens une erreur de segmentation (due au strncpy).

int main(void) {  

    char *str1 = "Big rectangle"; 
    char *str2 = "Square"; 

    struct point *p1 = create_point(10, 10); 
    struct point *p2 = create_point(100, 100); 

    struct rectangle *r1 = create_rectangle(*p1, *p2, str1); 
    print_rectangle(r1); 
    printf(" expecting: (10, 10) (100, 100) Big rectangle\n"); 

    free(p2); 
    p2 = create_point(20, 20); 

    struct rectangle r2; 

    strncpy(r2.label, str2, NAMESIZE); //GETTING SEGMENTATION FAULT DUE TO THIS LINE 
} 

Je pense que je reçois une erreur de segmentation fault parce que je fais strncpy directement sur r2.label. Je suspecte que parce que je n'alloue aucun espace à char *label dans la structure de rectangle est pourquoi j'obtiens une erreur de faute de segmentation. Mais quand j'écris

char *label = malloc(sizeof(NAMESIZE) * sizeof(char)); 

Je reçois une erreur:

error: expected ';' at end of declaration list` error. 
+0

Considérez soigneusement si 'strncpy' est vraiment l'outil idéal pour le travail. Ce n'est * pas * juste un "plus sûr" 'strcpy'. Voir [my rant sur le sujet] (http://the-flat-trantor-society.blogspot.com/2012/03/no-strncpy-is-not-safer-strcpy.html), ainsi que la question 13.2 de le [comp.lang.c FAQ] (http://www.c-faq.com/). (Je ne suggère pas que c'est la cause du problème que vous voyez.) –

+0

'malloc (sizeof (NAMESIZE) * sizeof (char))' - quoi? 'NAMESIZE' est un int donc cela alloue probablement 4 octets. –

Répondre

0

Apparemment, comme vous l'avez dit, vous n'allouez aucune mémoire pour votre char* label.

faire:

r2.label = malloc(sizeof(NAMESIZE) * sizeof(char));` 
0

Vous mallocstrlen(label) octets de l'étiquette dans create_rectangle, puis copiez dans strlen(label)+1 octets. Notez que si la nouvelle étiquette que vous copiez est plus longue, vous déborderez cette allocation. Mais comme le souligne @YuHao, cela n'a pas d'importance, car vous n'avez jamais initialisé aucun des champs de r2 (en particulier, label).

0
r->label = malloc(strlen(label) * sizeof(char)); 

Vous allocation Mising pour caractère de fin, il devrait être

r->label = malloc((strlen(label)+1) * sizeof(char)); 
4
strncpy(r2.label, str2, NAMESIZE); 

Vous essayez d'écrire à r2.label, qui est un pointeur qui n'a pas été alloué un espace.

Et soyez prudent avec le code que vous avez allouez de l'espace:

r->label = malloc(strlen(label) * sizeof(char)); 

strlen(label) ne suffit pas, une chaîne doit se terminer par.

+0

Que se passe-t-il si une chaîne n'est pas terminée par un caractère nul? – user2635911

+2

Ensuite, ce n'est pas une chaîne. La signification de * chaîne * est: série de caractères suivie d'une terminaison nulle. –

2

Ce code:

r->label = malloc(strlen(label) * sizeof(char)); 
strncpy(r->label, label, strlen(label) + 1); 

devrait être:

r->label = malloc(strlen(label) + 1); 
strcpy(r->label, label); 
  • Vous devez allouer de l'espace pour la terminaison nulle.
  • sizeof(char) est toujours 1
  • La fonction strcpy se termine après l'écriture strlen(label)+1 octets, il est donc inutile d'essayer d'utiliser strncpy.

strncpy est assez dangereux en général parce que parfois il ne sort pas une chaîne; mon conseil serait de ne jamais l'utiliser.

Plus bas,

strncpy(r2.label, str2, NAMESIZE); 

est faux parce r2.label est actuellement un pointeur sauvage. Vous devez également allouer de la mémoire de la même manière:

r2.label = malloc(strlen(str2) + 1); 
strcpy(r2.label, str2); 
+0

Y a-t-il un moyen de réserver de l'espace pour le littéral de chaîne d'étiquettes dans la structure elle-même? Quelque chose comme: char * label = malloc (sizeof (NAMESIZE) + 1); – user2635911

+0

Oui, passez à 'char label [NAMESIZE + 1];' –

+0

Arrêtez d'écrire 'sizeof (NAMESIZE)'. 'NAMESIZE' est' 20'. 'sizeof (NAMESIZE)' signifie 'sizeof (20)', c'est-à-dire le nombre d'octets requis pour stocker l'int '20'. Ce qui est 'sizeof (int)', qui est 4 ou 8 sur les systèmes communs. –

Questions connexes