Programmieren in C segmentation fault (core dumped) Fehler

Narut0Uzumaki

Newbie
Registriert
Aug. 2022
Beiträge
5
Hallo Leute,

ich bin noch ziemlich neu dabei und bekomme bei meinem Programm die obige Fehlermeldung. Habe ich den Speicher falsch allokiert? Versucht habe ich ein Programm zus chreiben, dass (a+b)^b berechnet. Das ist mein Code:


C:
#include <stdio.h>
#include <stdlib.h>

int* einlesen(int*, int*, int*);
int potenzieren(int*, int*, int*);

main()
{
int *a, *b, *n;


a = malloc(sizeof(int));

b = malloc(sizeof(int));

n = malloc(sizeof(int));


einlesen(a,b,n);

int ergebnis = potenzieren(a,b,n);

printf("%d",ergebnis);

 free(a);

 free(b);

 free(n);

}

int* einlesen(int *a,int *b,int *n){
    
    printf("Bitte geben sie a,b und n ein fuer (a+b)^n\n");
    scanf("%d %d %d",*a,*b,*n);
    
    
    return a;
    return b;
    return n;
}

int potenzieren(int *a, int *b, int *n){


if(*n == 0){
    return 1;
}
    
else {
    
    return ((*a + *b) * potenzieren(a, b, (n-1)));
}
}

Ich hoffe ihr könnt mir weiterhelfen :)
 
Zuletzt bearbeitet:
Narut0Uzumaki schrieb:
n ist doch auch ein Pointer, du änderst hier also die Adresse, was du sicher nicht willst.
BTW, wir haben richtig coole Codetags, die machen das viel lesbarer.
 
  • Gefällt mir
Reaktionen: madmax2010 und Narut0Uzumaki
Narut0Uzumaki schrieb:
int* einlesen(int *a,int *b,int *n){

printf("Bitte geben sie a,b und n ein fuer (a+b)^n\n");
scanf("%d %d %d",*a,*b,*n);


return a;
return b;
return n;
}
Eine Funktion hat maximal einen Rückgabewert. Sobald ein return erreicht wird, wird der entsprechende Wert zurückgegeben und der Durchlauf beendet. Also nach return a; ist zwangsläufig Schluss und alles was danach kommt wird nie ausgeführt.
 
  • Gefällt mir
Reaktionen: Narut0Uzumaki
Hey, danke für deine schnelle Antwort.
Ich weiß nicht ob das hier die richtige Antwortfunktion ist, aber ich hoffe du wirst benachrichtigt.
Vielen Dank, demnächst achte ich auf die Codetags.
pseudopseudonym schrieb:
n ist doch auch ein Pointer, du änderst hier also die Adresse, was du sicher nicht willst.
BTW, wir haben richtig coole Codetags, die machen das viel lesbarer.
Du hast Recht, n ist auch eine Adresse. Ich habe jetzt Mal versucht *n zu schreiben, damit vom Inhalt auf den der Pointer zeigt eins abgezogen wird. Mein Code schaut jetzt so aus, jedoch bekomme ich noch immer die Fehlermeldung :heul::

C:
#include <stdio.h>
#include <stdlib.h>

int* einlesen(int*, int*, int*);
int potenzieren(int*, int*, int*);

main()
{
int *a, *b, *n;
a = malloc(sizeof(int));
b = malloc(sizeof(int));
n = malloc(sizeof(int));

einlesen(a,b,n);
int ergebnis = potenzieren(a,b,n);
printf("%d",ergebnis);

free(a);
free(b);
free(n);
}

int* einlesen(int *a,int *b,int *n){
    
    printf("Bitte geben sie a,b und n ein fuer (a+b)^n\n");
    scanf("%d %d %d",*a,*b,*n);
    
    
    return a;
    return b;
    return n;
}

int potenzieren(int *a, int *b, int *n){


if(*n == 0){
    return 1;
}
    
else {
    *n - 1;
    return ((*a + *b) * potenzieren(a, b, n ));
}
}
 
Versuche ggf. erst einmal das Ergebnis von Einlesen zu prüfen indem du nach dem Aufruf den Wert von a, b und n ausgibst. Falls das funktioniert dann weiter.

C:
else {
    *n - 1;

Diese Zeile macht übrigens nicht das was du vermutlich willst ;)

Übrigens kannst du Beiträge hier auch editieren und damit den Code im Eingangspost noch in die Codetags verschieben.
 
  • Gefällt mir
Reaktionen: Narut0Uzumaki
Raybeez schrieb:
Eine Funktion hat maximal einen Rückgabewert. Sobald ein return erreicht wird, wird der entsprechende Wert zurückgegeben und der Durchlauf beendet. Also nach return a; ist zwangsläufig Schluss und alles was danach kommt wird nie ausgeführt.
Ok vielen Dank alle zusammen, ich habe es jetzt ^^. bei der Fehler war bei scanf

C:
#include <stdio.h>
#include <stdlib.h>

int* einlesen(int*, int*, int*);
int potenzieren(int*, int*, int*);

main()
{
int *a, *b, *n;
a = malloc(sizeof(int));
b = malloc(sizeof(int));
n = malloc(sizeof(int));

einlesen(a,b,n);
int ergebnis = potenzieren(a,b,n);
printf("%d",ergebnis);

free(a);
free(b);
free(n);
}

int* einlesen(int *a,int *b,int *n){
  
    printf("Bitte geben sie a,b und n ein fuer (a+b)^n\n");
    scanf("%d %d %d", a, b, n);
  
  
    return a;
    return b;
    return n;
}

int potenzieren(int *a, int *b, int *n){


if(*n == 0){
    return 1;
}
  
else {
    (*n)--;
    return ((*a + *b) * potenzieren(a, b, n ));
}
}

beim einlesen habe ich die werte auf *a,*b*n gespeichert. Ich hätte aber nur auf a,b,n speichern müssen. Ich danke euch allen für eure Mühen. Ihr habt mir weitergeholfen ♥!
 
  • Gefällt mir
Reaktionen: DaysShadow
Kleiner Denkanstoß:
- Warum arbeitest du auf dem Heap?
 
  • Gefällt mir
Reaktionen: pseudopseudonym und Narut0Uzumaki
Und was sollen 3 return-Statements hintereinander bringen? Vor allem, wenn du den zurückgegebenen Wert sowieso ignorierst?
 
  • Gefällt mir
Reaktionen: Narut0Uzumaki und abcddcba
Hii, jaa sorry habe ich vergessen zu korrigieren. Ich habe die rausgenommen und als Rückgabedatentyp void genommen (bei der Fkt. einlesen).
Ergänzung ()

titanskin schrieb:
Kleiner Denkanstoß:
- Warum arbeitest du auf dem Heap?
Sorry den Begriff habe ich bis jetzt noch nicht gehört. Ich habe ihn mal gegooglet. Falls du mich fragst, warum ich mit Zeigern arbeite etc: Ich verwende Zeiger, da mein Professor es als Übung so wollte. Ich hoffe ich habe deine Frage richtig verstanden :p
 
  • Gefällt mir
Reaktionen: tollertyp
Naja, Zeiger sind halt nicht gleich Zeiger.
Um nur "call by reference", was auch Zeiger sind, durchzuführen, braucht es noch keine dynamische Speicherverwaltung mit malloc und free. Dafür gibt es eigentlich keinen Grund. Wie die Parameter übergeben werden, kann man beim Funktionsaufruf angeben.

Wie gesagt, Stichwort ist z.B. "call by reference". Dann wird die Adresse des Werts übergeben, d.h. der Wert kann genutzt aber auch verändert werden. Bei "call by value" wird eine Kopie des Werts übergeben, d.h. der Aufrufer bekommt nur bedingt etwas von Änderungen mit (wenn es Zeiger sind, die übergeben werden, eben schon).

Beispiel: https://www.tutorialspoint.com/cprogramming/c_function_call_by_reference.htm

Wie du siehst hat die swap-Funktion quasi dieselbe Signatur wie deine Funktion (halt ein Parameter weniger), das "spannende" (ich hoffe alle haben Popcorn) ist halt der Aufruf mit dem &. Der macht aus einer "normalen" Variablen eben quasi einen Zeiger bzw. eine Referenz.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: titanskin, Narut0Uzumaki und andy_m4
Bei der Einlesefuntiom ergeben die Pointer Sinn, beim Rechnen nicht. Da kannst du ruhig direkt mit Werten arbeiten und hast die Kopfschmerzen nicht mehr.
 
@pseudopseudonym: Ja, bei der Einlese-Funktion ergeben die Zeiger/Referenzen Sinn, die dynamische Speicherverwaltung aber dennoch nicht wirklich.

Vor allem, und das ist das schlimmste, würde denke ich niemand erwarten, dass die Funktion "potenzieren" den Wert von n ändert. Macht es hier aber.

Wenn man am Ende nochmal die Eingabeparameter ausgeben würde, würde man das sehen.
 
Jup, n sollte definitiv kein Pointer sein (der Rest auch eher nicht).
 
  • Gefällt mir
Reaktionen: tollertyp
Und noch als Hinweis: Übungsaufgaben werden hier generell nicht so gerne gesehen. So wie es hier läuft ist es aber in meinen Augen okay, weil du nicht sagst "Macht mal bitte" und auch keiner dir die "Musterlösung" auf dem Silbertablett serviert.

Ich hoffe auch, dass kein Moderator hier überempfindlich reagiert. :-)

Und noch ein weiterer Hinweis:
Warum braucht die Funktion potenzieren überhaupt a und b als Eingangsparameter? Würde das nicht eleganter gehen?
Ich würde von einer Funktion, die potenzieren heißt, eigentlich zwei Eingangsparameter erwarten...
 
  • Gefällt mir
Reaktionen: Narut0Uzumaki
malloc kann weg (du brauchst in dem programm keinen dymanischen speicher).
somit kann auch free weg.

die funktion einlesen kann als void benutzt werden.
du willst da wahrscheinlich keinen neuen pointer returnen.
return a, b, c kann in der funktion auch raus

die variablen in der main müssen z. B. nicht als pointer deklariert werden.
du kannst auch die speicheradressen von normalen variablen an eine funktion übergeben.
würde dann so aussehen:
int a,b,c; // variablen deklarieren
einlesen(&a, &b, &c); // funktionsaufruf
void einlesen(int *a, int *b, int *c) {..} // funktion

was du in der funktion potenzieren versuchst zu machen, versteh ich nicht.
wenn du deinen code in dieser funktion kommentieren würdest, könnte man evtl. nachvollziehen, was du versuchst zu machen.


tut mir leid, aber dir fehlen die absoluten basics.
versuch das ganze einmal ohne pointer zu realisieren und schau, ob es dann das gewünschte ergebnis ausgibt. falls ja, kannst du dich zu pointern belesen und es dann damit probieren.

vllt noch n tipp: gerade als anfänger kann es sinn machen, alles zu kommentieren, um evtl. logikfehler von selbst zu erkennen.
 
Zuletzt bearbeitet von einem Moderator:
  • Gefällt mir
Reaktionen: Narut0Uzumaki
tollertyp schrieb:
Naja, Zeiger sind halt nicht gleich Zeiger.
Um nur "call by reference", was auch Zeiger sind, durchzuführen, braucht es noch keine dynamische Speicherverwaltung mit malloc und free. Dafür gibt es eigentlich keinen Grund. Wie die Parameter übergeben werden, kann man beim Funktionsaufruf angeben.

Wie gesagt, Stichwort ist z.B. "call by reference". Dann wird die Adresse des Werts übergeben, d.h. der Wert kann genutzt aber auch verändert werden. Bei "call by value" wird eine Kopie des Werts übergeben, d.h. der Aufrufer bekommt nur bedingt etwas von Änderungen mit (wenn es Zeiger sind, die übergeben werden, eben schon).

Beispiel: https://www.tutorialspoint.com/cprogramming/c_function_call_by_reference.htm

Wie du siehst hat die swap-Funktion quasi dieselbe Signatur wie deine Funktion (halt ein Parameter weniger), das "spannende" (ich hoffe alle haben Popcorn) ist halt der Aufruf mit dem &. Der macht aus einer "normalen" Variablen eben quasi einen Zeiger bzw. eine Referenz.
Vielen Dank für deine Antwort! Malloc und free() habe ich verwendet, da ich erstmal gegoogelt habe was man bei der Fehlermeldung machen kann. In einem Thread habe ich dann gesehen, wie einem gesagt wurde, dass er nicht genug Speicher allokiert hat. Deswegen habe ich versucht, die Warnung durch Malloc und free loszuwerden :freak:. Eine Frage zu dem Code, den du reingeschickt hast: Heißt das ich kann theoretisch einfach zwei normale variables definieren und bei der Parameterübergabe, dann einfach die Adresse übergeben und das sind dann automatisch zwei Zeiger? Ich hoffe das ist keine blöde Frage😅
Ergänzung ()

p0wnd schrieb:
malloc kann weg (du brauchst in dem programm keinen dymanischen speicher).
somit kann auch free weg.

die funktion einlesen kann als void benutzt werden.
du willst da wahrscheinlich keinen neuen pointer returnen.
return a, b, c kann in der funktion auch raus

die variablen in der main müssen z. B. nicht als pointer deklariert werden.
du kannst auch die speicheradressen von normalen variablen an eine funktion übergeben.
würde dann so aussehen:
int a,b,c; // variablen deklarieren
einlesen(&a, &b, &c); // funktionsaufruf
void einlesen(int *a, int *b, int *c) {..} // funktion

was du in der funktion potenzieren versuchst zu machen, versteh ich nicht.
wenn du deinen code in dieser funktion kommentieren würdest, könnte man evtl. nachvollziehen, was du versuchst zu machen.


tut mir leid, aber dir fehlen die absoluten basics.
versuch das ganze einmal ohne pointer zu realisieren und schau, ob es dann das gewünschte ergebnis ausgibt. falls ja, kannst du dich zu pointern belesen und es dann damit probieren.

vllt noch n tipp: gerade als anfänger kann es sinn machen, alles zu kommentieren, um evtl. logikfehler von selbst zu erkennen.
Vielen Dank! Ich achte demnächst darauf, meinen Code zu kommentieren. Ja, die Return variables habe ich bereits rausgenommen gehabt und als ausgang auch void(habe ich oben bei jemandem als Antwort geschrieben gehabt). Das Programm klappt und Malloc etc lasse ich jetzt weg. Vielen Dank für eure Hilfe alle zusammen ! 💕
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: kuddlmuddl
Narut0Uzumaki schrieb:
Heißt das ich kann theoretisch einfach zwei normale variables definieren und bei der Parameterübergabe, dann einfach die Adresse übergeben und das sind dann automatisch zwei Zeiger?
Die Parameter der Funktion sind Zeiger. Was ist denn der Wert eines Zeigers?

Allgemein noch fürs Lernen: Verstehe was du da genau machst, verwende nicht einfach nur wild irgendwas. Es ist absolut in Ordnung sich im Netz was zusammen zu suchen und wenn das Programm dann funktioniert, cool, aber setz dich nachfolgend unbedingt dran und verstehe was die Zeilen machen die du kopiert hast.

Zumindest wenn du in dem Bereich bleiben willst und es nicht für ein Fach in der Schule/Uni ist das du nur überleben musst und dann vergessen kannst 😉
 
  • Gefällt mir
Reaktionen: Narut0Uzumaki
Nachdem das Grobe geklärt ist, gibt es die zweite Frage:
- Warum ist solch eine Rekursion wie in "potenzieren" dumm?
 
Vermutlich willst du darauf hinaus, dass es den Stack "zumüllt". Aber da die Rekursion könnte vom Compiler problemlos optimiert werden.
 
Einen Punkt hast du zwar, nur solltest du nochmal über deinen Einwand sinnieren, warum er nicht gut ist.
  • Ist das wirklich so, dass es immer wegoptimiert wird? Wenn nein, welche Folgen hat es?
  • wie kann pow noch geschrieben werden? Wie kann es verwendet werden um an Multiplikationen zu sparen? Welche Folgen hat dann der gewählte Datentyp?
 
Zurück
Oben