2015-05-02 7 views
7

Der Titel möglicherweise verwirrend. Angenommen, str ist ein Zeiger, der von malloc zugewiesen wird. ptr vom Typ int*, wird es zugeordnet und freigegeben wird, wie unten durch den Codeausschnitt gezeigt:Wird ein int * freigegeben, das einem char * (von `malloc` zugewiesen) zugewiesen wurde, wird Undefined Behavior aufgerufen?

char* str = malloc(64); 
int* ptr = str; 

free(ptr); 

Ich habe versucht, den obigen Code zu kompilieren. Es gibt nur eine Warnung:

source_file.c: In function ‘main’: 
source_file.c:10:16: warning: initialization from incompatible pointer type 
    int* ptr = str; 
       ^

Führt der obige Code Undefined Behavior?
Macht der obige Code-Ausschnitt den von malloc für str zugeteilten Speicher frei?

+0

Welchen Compiler benutzen Sie? Der obige Code gibt 'error: kann 'char *' in 'int *' bei der Initialisierung mit gcc 4.9.2 nicht konvertieren. – farukdgn

+0

Ich dachte daran, diese Frage nach dieser einen Frage gestern ebenfalls zu stellen. Danke für das Nachschlagen ... :-) – alk

+0

@farukdgn, Habe diesen Fehler beim Kompilieren mit g ++ in C++ bekommen. GCC scheint es zu kompilieren. Ich benutze GCC 4.8.1. –

Antwort

11

Does the above code invoke Undefined Behavior?

Kommt drauf an.

Von C11 Entwurf 6.3.2.3/7:

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned) for the referenced type, the behavior is undefined.

Als Ausrichtung für ein char könnte von einem int anders sein, das ist wahrscheinlich weniger restriktiv, einen char * pc zu einem int * pi zuweisen könnte zu pi Wesen führen verstellt.

jedoch für das spezifische Beispiel durch das OP gegeben:

char * pc = malloc(64); 
int * pi = pc; 

das Verhalten würde definiert werden, wie (Siehe Alter Mann ‚s comment) malloc() garantiert einen Speicherblock zurück richtig ausgerichtet .

Von C11 Entwurf 7.22.3:

The pointer returned [by aligned_alloc, calloc, malloc, and realloc] if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement ...

Ein Beispiel, das würde führen zu undefinierten Verhalten, aufgrund einer Fehlausrichtung ist:

char * pc = malloc(64); 
int * pi = pc + 1; 

Does the above code snippet free the memory allocated by malloc for str?

Bei die frühere Zuordnung hätte undefiniertes Verhalten eingeführt, ist diese Frage irrelevant vant, da alles passieren könnte, weil UB bereits aufgerufen wurde.

Wenn sonst die vorherige Zuordnung nicht UB aufgerufen hat, würde der Aufruf von free() perfekt de-Zuweisung des Speicherblockes referenziert, als Umwandlung des Zeigerwertes int *-void * zurück, wie ursprünglich von malloc() vorgesehen ist, gut ist definiert.

Von C11 Entwurf 6.3.2.3/7 (Forts /):

Otherwise, when converted back again, the result shall compare equal to the original pointer

und

Von C11 Entwurf 6.3.2.3/1:

A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer

+3

Aber auf der anderen Seite: 'Der Block, den malloc Ihnen gibt, ist garantiert so ausgerichtet, dass er jede Art von Daten speichern kann.' –

+0

" * ist garantiert ausgerichtet * "ist es? – alk

+0

@alk: Ja, scheint so. – alk

0

Es berufen kann, UB, basierend auf endianness, Ausrichtungen oder so int vs char Schublade gesteckt, wenn zugegriffen. Wenn Sie malloc machen, geben Sie nur eine void* zurück, die von jedem Datentyp sein kann (und in einigen Fällen typecasting erfordert). Es macht keinen Unterschied, wenn Sie einen Zeiger in char * auf int * setzen, aber es würde einen Unterschied in den Zugriffseinheiten geben, d. H. Im Fall von Ints 4 Bytes gleichzeitig in Zeichen 1 Byte zu einem Zeitpunkt. Also, dieser Code in Ihrer Frage würde nicht UB aufrufen, aber Speicherzugriffe könnten.

Wie für die zweite Frage, ja ruft kostenlos auf ptr wird dazu führen, Speicher von str auch gezeigt, um freigegeben werden. Jetzt wäre str ein fliegender Zeiger.

+1

"* kann typecasting * erfordern" in C wird es nie. – alk

+0

In C++ würden Sie Typecasting benötigen. – askmish

+3

C und C++ sind nicht die gleiche Sprache. Diese Frage bezieht sich auf C. – alk

4

Nein. Es ruft nicht undefined Verhalten. Die Warnung bezieht sich einfach auf inkompatible Typen, die Sie verwenden könnten.

char* str = malloc(64); 
int* ptr = (int*) str; 
free(ptr); 

free hat einen void-Zeiger nehmen und das hat vor keine Probleme. Wenn Sie jedoch das Ergebnis eines solchen Werts verwenden, kann undefiniertes Verhalten aufgrund der Ausrichtung von Int-Typ und Zeichenart aufrufen. Daher führt die Umwandlung von char* zu int* selbst nicht zu undefiniert.

+0

Gemäß dem Standard (siehe meine Antwort), wenn die Ausrichtung des Zieltyps nicht angegeben ist, ruft die Zuweisung bereits UB auf. – alk

+0

Nicht sicher, welcher Teil, auf den Sie verwiesen haben, besagt, dass Zuweisung von char ptr zu int ptr zu UB führt. Wie ich in Antwort gesagt habe, nur * mit * könnte es UB führen. –

+0

Ich gab ein Beispiel in meiner Antwort auf, wenn nur die Assigment UB provozieren würde. Ihr Code sowie der OP-Code provozieren nicht UB. – alk

1

Does the above code invoke Undefined Behavior?

Nr

Does the above code snippet free the memory allocated by malloc for str?

Ja.

Nur zur Klarstellung, einige Hinweise auf UB in Bezug auf die dynamische Zuordnung:

Speicher zurück durch malloc ausgerichtet ist, einen möglichen Wert zu nehmen. Ein solcher Speicher hat keinen deklarierten Typ, und sein effektiver Typ wird über den Speicher festgelegt.

Wenn Sie

tun
*ptr = 42; 

die ersten sizeof (int) Bytes des Speicherblocks jetzt vom Typ sein int und nur als solche gelesen werden kann, das heißt

float val = *(float *)ptr; 

wird UB sein.

jedoch

*(float *)ptr = 42.0; 

wäre legal, da es wieder setzt die effektive Art, jetzt wiederum machen liest durch *ptr ungültig.

Darüber hinaus ist es immer legal, auf ein beliebiges Objekt über Zeiger vom Typ char oder unsigned char zuzugreifen.

+0

Es tut mir leid es stellt sich heraus, dass wenn ich vor 2 Tagen mit meinem Handy fummelte, ich Sie absichtlich downvooted. Ich kann es nicht ohne Bearbeitung rückgängig machen. –

+0

@ BlueMoon: keine Sorgen; technisch sollte dein Edit "char", "signed char" oder "unsigned char" lesen - das sind alles verschiedene Typen, obwohl 2 von ihnen die gleiche Darstellung haben werden;) – Christoph

+0

Richtig. Ich habe hauptsächlich nach einer einfachen Bearbeitung gesucht, anstatt irgendetwas zu korrigieren :) –

Verwandte Themen