Ich versuche, einen Zeiger von einer Funktion zurückzugeben. Aber ich erhalte einen Segmentierungsfehler. Jemand bitte sagen, was mit dem Code falsch ist
#include <stdio.h>
int *fun();
main()
{
int *ptr;
ptr = fun();
printf("%d", *ptr);
}
int *fun()
{
int *point;
*point = 12;
return point;
}
Weisen Sie Speicher zu, bevor Sie den Zeiger verwenden. Wenn Sie keinen Speicher zuweisen *point = 12
ist undefiniertes Verhalten.
int *fun()
{
int *point = malloc(sizeof *point); /* Mandatory. */
*point=12;
return point;
}
Auch dein printf
ist falsch. Sie müssen dereferenzieren (*
) der Zeiger.
printf("%d", *ptr);
^
Obwohl es eine schlechte Praxis ist, einen Zeiger auf ein lokales Objekt zurückzugeben, hat es hier nicht den Kaboom verursacht. Hier ist der Grund, warum Sie einen Segfault erhalten haben:
int *fun()
{
int *point;
*point=12; <<<<<< your program crashed here.
return point;
}
Der lokale Zeiger verlässt den Gültigkeitsbereich, aber das eigentliche Problem besteht darin, einen Zeiger zu dereferenzieren, der nie initialisiert wurde. Was ist der Punktwert? Wer weiß. Wenn der Wert keinem gültigen Speicherplatz zugeordnet wurde, erhalten Sie einen SEGFAULT. Wenn es glücklicherweise etwas Gültiges zugeordnet ist, haben Sie gerade den Speicher beschädigt, indem Sie diese Stelle mit Ihrer Zuweisung zu 12 überschrieben haben.
Da der zurückgegebene Zeiger sofort verwendet wurde, könnten Sie in diesem Fall mit der Rückgabe eines lokalen Zeigers davonkommen. Dies ist jedoch eine schlechte Praxis, da das Verhalten des Programms undefiniert wäre, wenn dieser Zeiger wiederverwendet würde, nachdem ein anderer Funktionsaufruf diesen Speicher im Stapel wiederverwendet hat.
int *fun()
{
int point;
point = 12;
return (&point);
}
oder fast identisch:
int *fun()
{
int point;
int *point_ptr;
point_ptr = &point;
*point_ptr = 12;
return (point_ptr);
}
Eine weitere schlechte Praxis, aber sicherere Methode wäre, den ganzzahligen Wert als statische Variable zu deklarieren, und er wäre dann nicht auf dem Stapel und wäre sicher vor der Verwendung durch eine andere Funktion:
int *fun()
{
static int point;
int *point_ptr;
point_ptr = &point;
*point_ptr = 12;
return (point_ptr);
}
oder
int *fun()
{
static int point;
point = 12;
return (&point);
}
Wie andere bereits erwähnt haben, wäre der “richtige” Weg, dies zu tun, Speicher auf dem Heap über malloc zuzuweisen.
Bei der Zuweisung des Werts 12 an den Integer-Zeiger wird kein Speicher zugewiesen. Daher stürzt es ab, weil es keinen Speicher findet.
Sie können dies versuchen:
#include<stdio.h>
#include<stdlib.h>
int *fun();
int main()
{
int *ptr;
ptr=fun();
printf("\n\t\t%d\n",*ptr);
}
int *fun()
{
int ptr;
ptr=12;
return(&ptr);
}
Meines Wissens macht die Verwendung des Schlüsselworts new relativ dasselbe wie malloc(sizeof identifier). Der folgende Code zeigt, wie das Schlüsselwort new verwendet wird.
void main(void){
int* test;
test = tester();
printf("%d",*test);
system("pause");
return;
}
int* tester(void){
int *retMe;
retMe = new int;//<----Here retMe is getting malloc for integer type
*retMe = 12;<---- Initializes retMe... Note * dereferences retMe
return retMe;
}
Die wichtigste Frage beim Umgang mit Zeigern ist: Zeiger auf was? Ein lokales Objekt? Kaboom. Ein dynamisch zugewiesenes Objekt? Von wem befreit? Ein Objekt woanders gespeichert? Wie lange lebt dieses Objekt dann und wie lange ist mein Zeiger gültig? Das Zurückgeben eines Zeigers von einer Funktion ist besonders riskant, da der Zeiger in einem völlig anderen Codestück initialisiert wird (das für den Aufrufer oft nicht einmal sichtbar ist) und die Aufrufer nicht wissen, wie sie mit dem Ergebnis umgehen sollen. Eine gute Dokumentation für solche Funktionen ist sehr wichtig.
– sbi
13. Oktober 2011 um 13:47 Uhr
Denken Sie nur daran, alle Objekte, Zeiger und Datenstrukturen immer zu mallocieren. Wenn Sie dies nicht tun, erhalten Sie immer einen Segmentierungsfehler, weil er nur besagt, dass wir Ihnen keinen Speicherplatz zuweisen.
– Kevin
13. Oktober 2011 um 14:07 Uhr
Wenn Sie “Fehler im Code ändern”, machen Sie die Antwort (teilweise) unabhängig von der Frage. Der fragliche Code ist nicht perfekt, das ist der Grund für die Frage. Ich empfehle dringend, in Fragen keinen Code zu korrigieren.
– Harfner
30. Mai 2014 um 17:29 Uhr
Hallo, was genau ist der Unterschied zwischen do it through
malloc
und mache es gerne*ptr = 12
? Warum gibt ersterer einen gültigen Zeiger an den Aufrufer zurück, selbst wenn er lokal im Absender deklariert ist, während letzterer dies nicht tut?– SexyBeast
3. Oktober 2015 um 12:30 Uhr
@AttitudeMonger Weil
malloc
sagt “Ich möchte etwas Speicher, um Sachen darin zu speichern”, aber einfach alt*ptr = 12
sagt “Ich möchte etwas Speicher, um eine Berechnung durchzuführen, die später für andere Dinge verwendet werden kann”.– wizzwizz4
9. April 2016 um 10:46 Uhr