2012-04-13 5 views
2

hey ich habe Probleme mit dem Operator sizeof in malloc. Siehe zum Beispiel den folgenden Abschnitt. Code-malloc (sizeof (s)) reserviert weniger Speicher als erwartet?

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
char * copy(char *s) 
{ 
    char *t=malloc(sizeof(s)); 
    char *ptr=s; 
    int i=0; 
    do 
    { 
     t[i++]=*ptr++; 
    } 
    while(*ptr!='\0'); 
    return t; 
} 
int main() 
{ 
    char *s="hello adsjahsjkdhjkashdkjaskdasldjlasjdlajsdlkjaslkdjalsjdlasjdljasdljasdkljklsdjlasdsadasdasd"; 
    char *b=copy(s); 
    printf("%s\n",b); 
    free(b); 
    return 0; 
} 

auf ideone, den Fehler gibt: - * glibc erkannt ./prog: free(): ungültige nächste Größe (schnell): 0x09bcf008 * *

Aber wenn ich ersetze malloc (sizeof (s)) durch malloc (strlen (s) +1), das Programm funktioniert perfekt. Also, was ist das Problem? HINWEIS: Dies ist nur ein kleines Prog, das ich erstellt habe, um das Problem zu demonstrieren, das ich in einem anderen Code hatte.

+0

Wenn 'malloc' * ever * weniger als angefordert zuweist (außer für * none * in diesem Fall gibt es' NULL' zurück), dann haben Sie einen Fehler in der Implementierung gefunden - - Herzliche Glückwünsche! –

Antwort

6

Der Operator sizeof macht nicht, was Sie auf Zeigern wollen. Es ergibt die Größe des Zeigers auf Ihrem Computer (der ungefähr 4 oder 8 sein wird).

Sie können sich das so vorstellen: Das Array zerfällt zu einem Zeiger, wenn es an eine Funktion übergeben wird und die Information bezüglich seiner Größe "verloren" ist.


Beachten Sie auch, dass Ihre Schleife den 0-Terminator nicht füllt.

+0

@ downvoter Können Sie eine Verbesserung vorschlagen? – cnicutar

6

Sie strlen statt sizeof in der copy Funktion verwendet werden soll:

char * copy(char *s) 
{ 
    char *t=malloc(strlen(s) + 1); 
    char *ptr=s; 
    int i=0; 
    do 
    { 
     t[i++]=*ptr++; 
    } 
    while(*ptr!='\0'); 
    return t; 
} 

Das Problem ist, dass sizeof nicht den Wert zurückgeben Sie benötigen, wird diese Funktion zurückgeben, die Größe des char *s (wahrscheinlich 4 oder 8 -> Bytes zum Speichern dieses Zeigers). Überprüfen Sie die Dokumentationslinks, um sie klarer zu verstehen.

Noch eine Sache, wenn Sie das tun, um Ihre C-Fähigkeiten zu üben ist in Ordnung, aber wenn Sie nicht sind, werden Sie wahrscheinlich nur die strcpy Funktion verwenden möchten.

Ich hoffe, es hilft.

+2

Noch nicht genug ... 'strlen' zählt nicht den Nullabschluss. – dmckee

+0

Sie haben Recht, bearbeitet. Danke @dmckee! –

+0

2 @ downvoters, bitte schlagen Sie eine Verbesserung vor .... Warum hat diese Frage noch keine Antwort ausgewählt? –

4

Arrays und Strings mit Größeninformationen auf Zeiger degeneriert wird seine Größe zu verlieren Attribute, wenn sie als Parameter an eine Funktion

So ist bestanden, wenn Sie die Größe des Parameters s es entweder die Berechnung kehrt 32/64 based auf deine Bittigkeit.

anstelle von sizeof, sollten Sie eigentlich strlen tun und fügen Sie ein, um das Null-Zeichen aufzunehmen.

statt

char *t=malloc(sizeof(s)); 

versuchen

char *t=malloc(strlen(s)+1); 

Bitte beachten Sie:

Es gibt auch andere Design-Probleme mit Ihrem Code

  1. Wenn ein Zeiger Argument übergeben, das ist nicht su Um sich zu ändern, sollten Sie es als const deklarieren.

  2. Im Allgemeinen ist die Rückgabe einer Adresse eines lokal generierten Heapspeichers keine gute Methode und die Hauptursache für Speicherverlust, wenn calle-lee es jemals vergisst, den Speicher freizugeben. Übergeben Sie es stattdessen als nicht konstanten Parameter an die Funktion.

+0

Anonyme Downvoter klären – Abhijit

4

sizeof(s) gibt die Größe char *s die 4 (auf 32 Bit) oder 8 (auf 64 Bit) Systemen.

1

sizeof gibt die Größe des Zeigers (normalerweise 4 oder 8 Byte) zurück, nicht die Größe des zugespitzten Objekts. (Es gibt keine Möglichkeit, an letzteren Informationen zu erhalten sizeof effektiv ein Kompilierung-Konstante, übrigens.).

1

s ist ein Zeiger auf char, so malloc(sizeof(s)) reserviert Speicherplatz für einen Zeiger auf char - in der Regel 2 -8 Bytes, meistens 4 Bytes. So wie es steht, wird es immer diese feste Menge an Speicherplatz zuweisen, unabhängig von der Länge der Zeichenfolge, die Sie übergeben haben. In Ihrem Test übergeben Sie eine viel längere Zeichenfolge als das, so dass Sie den zugewiesenen Puffer überlaufen.

Sie haben bereits die richtige Antwort erhalten: unter diesen Umständen ist strlen die richtige Funktion, um die Größe zu finden.

0

malloc ist in deklariert, so dass wir diesen Header in jedem Programm, das malloc aufruft, einschließen. Ein "Byte" in C ist definitionsgemäß eine Speichermenge, die zum Speichern eines Zeichens geeignet ist, so dass der obige Aufruf von malloc genau so viele Zeichen enthält, wie wir verlangen. Wir könnten den resultierenden Zeiger wie folgt darstellen:

+0

mögen: ??? Ich denke, du hast es verpasst, dort etwas Code zu platzieren. –

Verwandte Themen