segmentation fault
-
hallo,
ich habe ein problem, und zwar funktioniert mein code mit gcc unter linux kompiliert einwandfrei, aber nicht einwandfrei unter windos mit dev c++ kompiliert.
also:
ich habe (bei dem mit gcc kompilierten code) eine unbekannte groesse von pointern, die jeweils auf den anfang eines structs zeigen sollen:
struct dvd **data;
spaeter dann gebe ich die anfangsadresse des reservierten speichers der struktur an den pointer zurueck:
data[i++] = dvd_add();
wie gesgagt, mit dem gcc unter linux klappt das einwandfrei, wenn ich das ganze nun aber mit dem dev c++ kompiliere, dann bekomme ich einen segmentation fault bei dieser zeile:
data[i++] = dvd_add();
wenn ich das pointer array nun mal statisch mache, dann klappt das ganze, z.b:
struct dvd *data[100];
ich wuerde aber gerne ein dynamisches array haben...
und jetzt die fragen:
ist der unter linux kompilierte code korrekt, oder funktioniert er nur durch zufall? (ich habe schon mehrere tausend adressen in das array kopieren koennen...)
was gibt es fuer loesungen?
-
Du musst auch Speicher für data reservieren, nicht nur für data[i].
-
wie muesste das denn aussehen? irgendwie komme ich nicht drauf...
-
data = malloc( ANZAHL_DER_ELEMENTE * sizeof(*data) );
-
und wenn die anzahl der elemente nicht feststeht, muss ich dann jedes mal mit realloc arbeiten, oder gibt es da noch einen eleganteren weg?
und warum funktioniert der code mit dem gcc kompiliert unter linux?
-
Moh schrieb:
und wenn die anzahl der elemente nicht feststeht, muss ich dann jedes mal mit realloc arbeiten, oder gibt es da noch einen eleganteren weg?
Ja, realloc(). Oder eine verkettete Liste.
Moh schrieb:
und warum funktioniert der code mit dem gcc kompiliert unter linux?
Undefiniertes Verhalten. Es ist reines Glück/Unglück dass es funktioniert.
-
> und wenn die anzahl der elemente nicht feststeht, muss ich dann jedes mal mit realloc arbeiten, oder gibt es da noch einen eleganteren weg?
realloc> und warum funktioniert der code mit dem gcc kompiliert unter linux?
aeh, undefiniertes verhalten z.b. nicht jeder fehler fuehrt unmittelbar zum segfault. eben diese fehler sind aber umso fieser, weil du erst spaeter merkst, dass du nen fehler gemacht hast.edit: lol
kann mal einer das forum mit ajax aufmotzen, damit ich beim schreiben seh, wenn neue posts geschrieben werden?
-
Moh schrieb:
und wenn die anzahl der elemente nicht feststeht, muss ich dann jedes mal mit realloc arbeiten, oder gibt es da noch einen eleganteren weg?
C++
-
Neku schrieb:
C++
dann frag dich mal, wie das dort gemacht wird: verkettete listen und permanent new und delete. auch nicht gerade optimal.
vorteil von klassen und objekten (oder built-in krempel): du hast ne abstraktionsschicht zwischen dem speichergefrickel und der eigentlichen benutzung. das macht ungemein produktiver und verhindert eine ganze menge fehler.
-
ich danke euch, habt mir sehr geholfen
-
ich habe noch einmal ergaenzende fragen:
wenn ich nun speicher fuer meine pointer reserviere, damit diese adressen speichern koennen:
data = malloc(ANZAHL_DER_ELEMENTE * sizeof(*data));
wie gebe ich den speicher den die pointer belegen wieder frei?
einfach mit:
free(*data[element_x]);
?
und noch einmal zur sicherheit, wenn ich schreibe:
free(data[element_x]);
dann gebe ich den speicher frei, auf den die adresse zeigt, oder?
-
Moh schrieb:
einfach mit:
free( *data[ element_x ] );
Nein! Damit würdest du ja data[ element_x ] dereferenzieren.
[edit]
...damit würdest du versuchen den Speicher freizugeben, dessen Adresse an data[element_x][0] steht, und das gibt ganz großen Käse
[/edit]Moh schrieb:
und noch einmal zur sicherheit, wenn ich schreibe:
free( data[ element_x ] );
dann gebe ich den speicher frei, auf den die adresse zeigt, oder?
Jup.
Ein kleines Beispiel:
#include <stdlib.h> #include <stdio.h> #include <string.h> #define NUM_STRINGS 10 int main( ) { const char *map[] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; char **string_array = ( char** ) malloc( NUM_STRINGS * sizeof( char* ) ); for( int i = 0; i < NUM_STRINGS; ++i ) { string_array[ i ] = ( char* ) malloc( strlen( map[ i ] ) + 1 ); // 1) strcpy( string_array[ i ], map[ i ] ); } for( int i = 0; i < NUM_STRINGS; ++i ) printf( "%s\n", string_array[ i ] ); // Aufräumen: for( int i = 0; i < NUM_STRINGS; ++i ) free( string_array[ i ] ); // den bei 1) reservierten Speicher für die Strings freigeben free( string_array ); // das Array aus NUM_STRINGS aus Zeigern auf char* freigeben }
Greetz, Swordfish
-
aehm okay, dein post ist mehr verwirrend als dass er mir hilft...
data = malloc( ANZAHL_DER_ELEMENTE * sizeof( data* ) )
warum muss es so lauten? das geht doch gar nicht, schon allein rein logisch... oder bin ich da jetzt vollkommen auf dem falschen weg?
wenn ich habe:
struct irgendwas **data;
dann speicher fuer die pointer reserviere:
data = malloc(ANZ_POINTER * sizeof(*data));
wie gebe ich den speicher, den die pointer einnehmen, konnkret wieder frei?
-
Swordfish schrieb:
Moh schrieb:
data = malloc(ANZAHL_DER_ELEMENTE * sizeof(*data));
muss
data = malloc( ANZAHL_DER_ELEMENTE * sizeof( data* ) );
heißen.
Ähmmm, nein.
-
@TactX: Oh, shit! Tschuldige. Ahhh. Er dereferenziert data einmal... ich hab' zu schnell gelesen und gedacht, data sei ein Typ. Mann bin ich blöd.
Greetz, Swordfish
-
Swordfish schrieb:
@TactX: Oh, shit! Tschuldige. Ahhh. Er dereferenziert data einmal... ich hab' zu schnell gelesen und gedacht, data sei ein Typ. Mann bin ich blöd.
Jetzt sei nicht so hart zu dir
PS: Warum castest du eigentlich malloc()?
-
Moh schrieb:
data = malloc(ANZ_POINTER * sizeof(*data));
wie gebe ich den speicher, den die pointer einnehmen, konnkret wieder frei?
mit:
for( int i = 0; i < ANZ_POINTER; ++i ) free( data[ i ] ); free( data );
Das sollte dir eigentlich mein Beispiel (oben) erklären.
BTW, @TactX: Findest du meinen Post auch so verwirrend!? (Ich mein, abgesehen von den ehemals dagewesenen Fehlern?)
TactX schrieb:
Jetzt sei nicht so hart zu dir
ne, verstehst, da beginnt man, an Fraktale (Terrains, Bäume, Gräser...) und Neurale Netze zu denken und dann sowas, nene...
TactX schrieb:
Warum castest du eigentlich malloc()?
Ich liieebe Casts!
Nee, will mein MSVS 2003 .net so.
Greetz, Swordfish
-
TactX schrieb:
PS: Warum castest du eigentlich malloc()?
damit sein c++ compiler das schluckt
-
Swordfish schrieb:
TactX schrieb:
Warum castest du eigentlich malloc()?
Ich liieebe Casts!
Nee, will mein MSVS 2003 .net so.
du musst die dateien .c nenen, das könnte ihn milde stimmen...
-
Swordfish schrieb:
BTW, @TactX: Findest du meinen Post auch so verwirrend!? (Ich mein, abgesehen von den ehemals dagewesenen Fehlern?)
Nö. Aber mir erst durch diesen Hinweis bewusst geworden, dass Moh bereits geantwortet hat
-
damit sein c++ compiler das schluckt
AAhhrrgll (ich druck's grad aus -> Wallpaper...
)
Greetz, Swordfish