2017-06-28 2 views
-1
#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <string.h> 

typedef struct _person 
{ 
    char *fname; 
    char *lname; 
    bool isavailable; 
}Person; 


Person *getPersonInstance(void) 
{ 
    Person *newPerson = (Person*) malloc(sizeof(Person)); 
    if(newPerson == NULL) 
     return NULL; 
    return newPerson; 
} 

void initializePerson(Person *person, char *fname, char *lname, bool isavailable) 
{ 
    person->fname = (char*) malloc(strlen(fname)+1); 
    /*problematic behaviour if i write: person->fname = (char*) malloc (sizeof(strlen(fname)+1)); */ 

    person->lname = (char*) malloc(strlen(lname)+1); 
/*problematic behaviour if i write: person->lname = (char*) malloc (sizeof(strlen(lname)+1)); */ 

    strcpy(person->fname,fname); 
    strcpy(person->lname,lname); 
    person->isavailable = isavailable; 

    return; 

} 

// test code sample 
int main(void) 
{ 
    Person *p1 =getPersonInstance(); 
    if(p1 != NULL) 
     initializePerson(p1, "Bronze", "Medal", 1); 

    Person *p2 =getPersonInstance(); 
    if(p2 != NULL) 
     initializePerson(p2, "Silver", "Medalion", 1); 

    Person *p3 =getPersonInstance(); 
    if(p3 != NULL) 
     initializePerson(p3, "Golden", "Section", 1); 

    printf("item1=> %10s, %10s, %4u\n",p1->fname, p1->lname, p1->isavailable); 
    printf("item2=> %10s, %10s, %4u\n",p2->fname, p2->lname, p2->isavailable); 
    printf("item3=> %10s, %10s, %4u\n",p3->fname, p3->lname, p3->isavailable); 

    return 0; 
} 

Innen initializePerson(), wenn ich benutze:malloc, sizeof und strlen funktionen möglich confict?

person->fname = (char*) malloc (sizeof(strlen(fname)+1)); 
person->lname = (char*) malloc (sizeof(strlen(lname)+1)); 

Wenn diese beiden Codezeilen anstelle von denen, aktiviert i oben im Quellcode verwenden, ich könnte einen Laufzeitfehler erhalten, wenn ich den Test Code mit CodeBlocks IDE. Sehr wahrscheinlich friert die Konsole ein und funktioniert nicht mehr. Wenn ich den Code mit Ubuntu-Terminal teste, funktioniert es jeden Tag ohne Probleme, unabhängig von der Größe der Eingabedaten.

Frage: (Nun, angenommen, dass wir die 2 Teile des Codes aus dem vorherigen Absatz verwenden) Ich weiß, dass Größe Bytes zählt, und Strlen zählt die Anzahl der Zeichen, bis es Null findet ... ABER sizeof und strlen wann Werden sie in malloc() zusammen verwendet, verursachen sie einen Konflikt im Hintergrund? Was scheint das Problem zu sein? Warum hat der Code so ein unberechenbares, unzuverlässiges Verhalten? Warum?

+0

[Verwirf das Ergebnis nicht von 'malloc' in C] (http://stackoverflow.com/q/605845/995714) –

+0

Warum sollte die * Größe * von die Länge ist gleich dem tatsächlichen * Wert * der Länge? –

+0

BTW, in einem Fall wie Ihnen, wenn es erforderlich ist, Speicher für die Zeichenfolge zuzuweisen und dann aus einer anderen Zeichenfolge zu kopieren, ist es einfacher, 'strdup 'zu verwenden, das drei Funktionen kombiniert:' strlen', 'malloc' und' strcpy' – Eugene

Antwort

4

sizeof wertet die Speichergröße des Arguments aus (das ein Ausdruck eines Typs oder nur der Typ selbst sein kann). Also, schauen genau, was das Argument hier ist:

strlen(fname)+1 

Dies ist ein Ausdruck des Typs size_t. sizeof wird Ihnen geben, welche Menge an Bytes benötigt wird, um eine size_t (wahrscheinlich entweder 4 oder 8) zu speichern.

Was Sie wollen ist genug Speicher für Ihre Zeichenfolge, so dass die Version mit nur strlen() die richtige ist. Im anderen Fall reservieren Sie nur 4 oder 8 Bytes und schreiben dann in Speicherbereiche, die Sie nicht zugeordnet haben ->undefiniertes Verhalten.


Auf einer seitlichen Anmerkung: void * Gießen explizit benötigt wird, nicht in C und wird durch viele schlechte Praxis betrachtet (aber nicht alle) Coder C. Siehe this classic quesion.

5

sizeof(strlen(fname)+1) macht keinen Sinn. Er gibt die Größe des Ergebnistyps strlen an, der eine Ganzzahl von 4 Byte ist. Sie reservieren also zu wenig Speicher.

verwenden:

person->fname = malloc(strlen(fname)+1);