PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C]Crash aufgrund von malloc, aber nur ohne Debugging


Sinner
2009-07-10, 18:59:02
Hi Leute,
ich hab n seltsames Problem. Es geht um ein Programm mit ca. 3000 Zeilen Code in c, entwickelt in Visual Studio. Im Debugging modus (start mit F5), läuft es tadellos.
Sobald man es allerdings mit Strg-F5 startet, also quasi "normal", crasht es. Und zwar wegen nem malloc. :(


struct Tile *tile = NULL;
....
....
tile = (struct Tile*) malloc (tile_number_total * sizeof (struct Tile));


Ich deklarier es ganz brav oben im Funktionskopf, und will dann den Speicher allokieren. Der komische Cast vor dem malloc hat keinen Einfluss, verhält sich genau gleich wenn ich den weglass.

Includes hab ich 2:

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


Version vom VIsual Studio ist "Visual Studio C++ 2008 Express".

Habt ihr ne Idee woran das liegen könnte? Hiiiillffeeeee, schon so viel Zeit in Debugging gesteckt und jetzt gehts immer noch net :(

Grüße Sinner

pest
2009-07-10, 19:55:12
Der komische Cast vor dem malloc hat keinen Einfluss


du weißt schon was du tust, oder?

dein fehler muss nicht bedeuten das das malloc fehlschlägt,
wahrscheinlich gerät vorher irgendein pointer ausser rand und band, deswegen gehts auch im debug-modus

Neomi
2009-07-10, 20:01:20
Der Fehler liegt nicht in dem Teil des Codes, den du gepostet hast. Wahrscheinlich hast du irgendwo uninitialisierte Variablen oder du hast über allokierte Grenzen hinweg bzw. mittels invalider Pointer Daten geschrieben. Kann auch was ganz anderes sein, aber ohne passenden Code läßt sich da nichts genaueres sagen.

Sinner
2009-07-11, 13:58:22
du weißt schon was du tust, oder?

dein fehler muss nicht bedeuten das das malloc fehlschlägt,
wahrscheinlich gerät vorher irgendein pointer ausser rand und band, deswegen gehts auch im debug-modus
Ja ich hoffe mal, dass ich weiß was ich tue.Über das malloc habe ich mich mal noch bisle schlau gemacht, ob man da nen Cast benutzen sollte hat wohl mit dem C-Standard zu tun und welchen Compiler man benutzt. Aber ich denke da sollte Visual Studio ja korrekt eingestellt sein. (Hab in den Einstellungen auch eingestellt, dass er die Option /TC benutzt, also explizit als C Code kompiliert.) Es sollte also egal sein, ob man den Cast benutzt.

Aber wenn ein Pointer außer Rand und Band gerät, wieso geht es dann im Debugging Modus? Ich mein, wir benutzen ja keine "Spaß"-Pointer, jeden Pointer den wir benutzen verweist auf wichtige Daten, und wenn da was schief läuft, sieht man das recht schnell am Resultat. (Ist ne JPEG2000 implementierung, d.h. das Ergebnisbild müsste dann ja in irgend einer Art scheiße aussehen)

Benutzt der Debugger irgendwie nen geschützten/speziellen Speicherbereich oder so? Anders kann ich mir das eigentlich nicht erklären... Werde heute abend mal noch den Code posten!

Grüße Sinner

*Edit: Hier schonmal der Code aus dem Testprogramm, wegen dem anderen Code muss ich noch meinen Teamkollegen fragen:

int main(){
struct Bitmap img;
struct Picture *pic = NULL;
struct Buffer buffer;
int j=0;
int i;
int status;
FILE *fp;
bmpReset(&img);
status = bmpRead(&img, "hd.bmp");
printf("BMP_Read fertig");

if(status != 0) {
printf("bmpRead returned error!\n");
return 1;
}

pic= malloc (sizeof(struct Picture*));
printf("\n Start Tiling");
pic = tiling (&img, 0);


-----------------------------------------
Weiter wie hier kommt er nicht, es passiert also wohl in der tiling-Funct:


Die Tiling Funktion:

struct Picture* tiling (struct Bitmap *img, int tilesize){
struct Picture *pic = NULL;
struct Tile *tile = NULL;
int work_tilesize , tile_number;
int xstep, ystep;
int tile_numberx, tile_numbery,tile_number_total;
int x, y, xpos, ypos, xDim, yDim;
int chan, pixel;
/*"work"-pointer*/
unsigned char **temp = NULL;
unsigned char **imgData = (unsigned char**)img->imgData;

/*Transfering data from original image to container*/
pic = malloc (sizeof (struct Picture));
pic->xSize = img->xDim;
pic->ySize = img->yDim;
pic->channels = img->channels;
pic->type = img->type;
/*Save original picture*/
pic->original = malloc (sizeof (struct Bitmap*));
pic->original->channels = img->channels;
pic->original->imgData = img->imgData;
pic->original->type = img->type;
pic->original->xDim = img->xDim;
pic->original->yDim = img->yDim;

if (pic->type != BMP_INT_8BIT){
printf ("Tiling: ERROR! Wrong input format");
return NULL;
}


/*standard tilesize set to 256x256*/
work_tilesize = 256;
tile_number = 0;
if (tilesize > 0){
work_tilesize = tilesize;
}
xstep = work_tilesize;
ystep = work_tilesize;


/*Calculation of tile number to allocate memory*/
tile_numberx = (pic->xSize + (work_tilesize - 1))/work_tilesize;
tile_numbery = (pic->ySize + (work_tilesize - 1))/work_tilesize;
tile_number_total = tile_numberx * tile_numbery;
printf("davor");
tile = malloc (tile_number_total * sizeof (struct Tile));
pic->tiles = tile;
printf("danach");
....
---------------------------------
Bis hinter dieses malloc kommt er nicht.Das "davor" spuckt er noch aus,
bis zum "danach" kommt er nicht mehr. Das tilenumbertotal hat den
Wert 35 beim aktuellen Beispiel, klappt also auch...

pest
2009-07-11, 14:07:58
der cast dient imo nur dazu weil malloc einen void* pointer zurückliefert


Aber wenn ein Pointer außer Rand und Band gerät, wieso geht es dann im Debugging Modus? Ich mein, wir benutzen ja keine "Spaß"-Pointer, jeden Pointer den wir benutzen verweist auf wichtige Daten, und wenn da was schief läuft, sieht man das recht schnell am Resultat. (Ist ne JPEG2000 implementierung,

also ich hatte das problem auch schon (einmal :D) und ich habe mich dumm und dämlich gesucht ;) - vor allem ist es immer an verschiedenen stellen abgeschmiert

und das resultat kann trotzdem funktionieren. überlege dir doch einfach ein bild mit 512x512 pixeln. wenn du da in zeile 513 schreibst ist das bild immernoch richtig

ersetzte testweise das malloc durch eine statische variable und spiele das
ganze durch. man muss das schon durchtesten um eine ahnung davon zu bekommen, was eigentlich schief läuft.

das es im debug läuft kann versch. ursachen haben. kenne den microsoft-compiler nicht, aber z.b. könnte der im debug-modus felder automatisch auf 0 bei malloc setzten (was sonst nicht passiert) und range-checking benutzen

Superguppy
2009-07-11, 15:18:54
Hier stand Müll.

Der_Donnervogel
2009-07-11, 19:08:10
Eins vorweg, ich bin nicht der große C-Experte, da ich versuche diese Sprache zu vermeiden, wo es nur geht, aber

pic->original = malloc (sizeof (struct Bitmap*));
pic->original->channels = img->channels;
pic->original->imgData = img->imgData;
pic->original->type = img->type;
pic->original->xDim = img->xDim;
pic->original->yDim = img->yDim;

Könnte es sein, dass hier nur Platz für einen Pointer, statt für die ganze Struktur reserviert wird, und dann die folgenden Zuweisungen etwas überschreiben? Müsste es statt sizeof (struct Bitmap*) nicht sizeof (struct Bitmap) sein?

Neomi
2009-07-11, 19:51:05
Könnte es sein, dass hier nur Platz für einen Pointer, statt für die ganze Struktur reserviert wird, und dann die folgenden Zuweisungen etwas überschreiben?

Stimmt genau, dadurch wird der Heap korrumpiert, was für nachfolgende Heapoperationen fatal ist.

Nebenbei noch ein Speicherleck:
In der Funktion main() wird Speicher allokiert und der Pointer darauf in pic abgelegt, pic wird kurz darauf aber wieder überschrieben. Der Pointer auf den unnötig reservierten Speicherbereich und damit der Speicherbereich selbst ist durch die Aktion verloren, quasi ein Leck.

Sinner
2009-07-12, 15:36:49
Eins vorweg, ich bin nicht der große C-Experte, da ich versuche diese Sprache zu vermeiden, wo es nur geht, aber

Könnte es sein, dass hier nur Platz für einen Pointer, statt für die ganze Struktur reserviert wird, und dann die folgenden Zuweisungen etwas überschreiben? Müsste es statt sizeof (struct Bitmap*) nicht sizeof (struct Bitmap) sein?

Ja genau, das wars! Danke dir! Aber ist doch komisch, dass er im Debug deswegen nicht auch abgestürzt ist oder zumindest ne Fehlermeldung gebracht hat.Hmmm.



Nebenbei noch ein Speicherleck:
In der Funktion main() wird Speicher allokiert und der Pointer darauf in pic abgelegt, pic wird kurz darauf aber wieder überschrieben. Der Pointer auf den unnötig reservierten Speicherbereich und damit der Speicherbereich selbst ist durch die Aktion verloren, quasi ein Leck.

Ja, ich fürchte Speicherlecks tummeln sich noch einige in unserem Programm. Naja, debugging ist ja bekanntlich die zeitintensivste Phase :D

Gast
2009-07-13, 16:30:16
Ja genau, das wars! Danke dir! Aber ist doch komisch, dass er im Debug deswegen nicht auch abgestürzt ist oder zumindest ne Fehlermeldung gebracht hat.Hmmm.


Dieser Fehler passiert jedem mal, aber was du sonst so schreibst ... auweia. Was sollte die Diskussion mit dem Cast. Mit dem Fehler hat das absolut nichts zu tun. Das mit dem Debug - Mode ist nur Zufall. Dort könnte es genau so krachen. Ein Prozess stürzt nur dann ab, wenn Speicher gelesen oder beschrieben wird, der nicht zum Prozess gehört.


Ja, ich fürchte Speicherlecks tummeln sich noch einige in unserem Programm. Naja, debugging ist ja bekanntlich die zeitintensivste Phase :D

Du weisst aber schon wie man die mit Visual Studio finden kann oder? Ich glaube du solltest dich nochmal richtig auf den Hosenboden setzen und etwas mehr über C und der verwendeten IDE lernen.

Coda
2009-07-13, 19:12:32
Ich habe hiermit sehr gute Erfahrungen gemacht über die Jahre:
http://www.paulnettle.com/pub/FluidStudios/MemoryManagers/

Erkennt zuverlässig alle Leaks und zeigt einem auch direkt die Codezeilen an an dem sie entstanden sind. Zusätzlich werden Fehler wie new[]/delete statt delete[] erkannt.

Falls man Linux verwendet ist natürlich valgrind (http://valgrind.org/) ein unglaublich mächtiges Tool.

Sinner
2009-07-13, 21:35:34
Ich habe hiermit sehr gute Erfahrungen gemacht über die Jahre:
http://www.paulnettle.com/pub/FluidStudios/MemoryManagers/

Erkennt zuverlässig alle Leaks und zeigt einem auch direkt die Codezeilen an an dem sie entstanden sind. Zusätzlich werden Fehler wie new[]/delete statt delete[] erkannt.

Falls man Linux verwendet ist natürlich valgrind (http://valgrind.org/) ein unglaublich mächtiges Tool.

Ui cool, danke für den Tip. Dieser Memory test von fluid studios ist ja in c++. Mit c++ kenn ich mich leider gar nicht aus, aber hab schon gesehen, dass man in cpp-Code mit extern C{...} wohl normale C Header Files einbinden kann.Aber geht das Programm für C-Code dann schon?

@Gast:
Ok, das mitm cast war offtopic, das hatte mich zuvor etwas verwirrt.Aber klar, wenn man die Hintergründe kennt isses ja kein Ding.

Und ja, mein C-Wissen ist echt nicht so super, ich programmier damit aber auch noch nicht so lange ;). Und den Debugger hab ich durchaus auch schon entdeckt, aber auch mit dem stößt man leider manchmal an Grenzen. Oder meinst du was anderes wie den Debugger? (wurde quasi "gezwungen" Visual Studio zu benutzen, hab davor in eclipse gecodet. Aber leider funktioniert CUDA wohl nur mit Visual Studio, und das brauchen wir später für das Projekt noch...)

Coda
2009-07-13, 22:30:46
Das sollte auch für C gehen, ja. Du solltest praktisch überall auch einfach C++ verwenden können im Projekt.

Der_Donnervogel
2009-07-15, 23:29:23
Und ja, mein C-Wissen ist echt nicht so super, ich programmier damit aber auch noch nicht so lange ;). Und den Debugger hab ich durchaus auch schon entdeckt, aber auch mit dem stößt man leider manchmal an Grenzen. Oder meinst du was anderes wie den Debugger? (wurde quasi "gezwungen" Visual Studio zu benutzen, hab davor in eclipse gecodet. Aber leider funktioniert CUDA wohl nur mit Visual Studio, und das brauchen wir später für das Projekt noch...)Visual Studio ist eh super komfortabel, da gibt es weit schlimmeres. Ich mußte mal was für ein Embedded Gerät machen. Da war nichts mit debuggen. Stattdessen war printf auf die serielle Schnittstelle angesagt wenn man Infos haben wollte, was das Programm gerade macht. Dazu kam dann noch das Warten bis der Programmer das Programm geflasht hatte, falls man was am Code geändert hat. Da ist dann Fehlersuche in C Programmen wirklich zäh (zumal wenn auch noch Inline Assembler drinn ist) und nicht so entspannend wie unter Visual Studio am PC. ;)

noid
2009-07-15, 23:32:30
Visual Studio ist eh super komfortabel, da gibt es weit schlimmeres. Ich mußte mal was für ein Embedded Gerät machen. Da war nichts mit debuggen. Stattdessen war printf auf die serielle Schnittstelle angesagt wenn man Infos haben wollte, was das Programm gerade macht. Dazu kam dann noch das Warten bis der Programmer das Programm geflasht hatte, falls man was am Code geändert hat. Da ist dann Fehlersuche in C Programmen wirklich zäh (zumal wenn auch noch Inline Assembler drinn ist) und nicht so entspannend wie unter Visual Studio am PC. ;)

Ohne JTAG-Debugger ist das wie tapezieren eines Flures durch das Schlüsselloch. ;(

Gast
2009-08-02, 17:13:06
Ohne JTAG-Debugger ist das wie tapezieren eines Flures durch das Schlüsselloch. ;(

^^ you made my day!

blöd ist nur, wenn die HW-Entwicklung bei nem BGA-Chip vegessen hat, die JTAG-Schnittstelle auch nach außen zu führen. Hab schon mal son Teil gekriegt - war nicht sonderlich komisch

mfg,
zgep