malloc() size problems


V

voidexp

Hi to all!

I have a strange problem with malloc(). I'm writing a 2D Game Engine,
for learning purposes, and I can't go forward without understanding
the problem... So I have a function:

Sprite* CreateSprite(char *filename);

which accepts a string containing a path to an image (PNG file for
example) and returns a pointer to a struct "Sprite". Nothing complex,
Sprite is a simple typedef for SDL_Surface structure, which is used to
represent surfaces in SDL (a multimedia library), and my function uses
IMG_LoadImage() for data loading. The problem is, when I load some
images (5-6 for example) with a variable size, say from 75k to 500k,
at sixth call of CreateSprite() my program exits with malloc error
message (heap corruption, or something like this). I'm usually
programming in Linux, but the problem persists in windows too. I found
a "solution" to split images in smaller tiles, that aren't greater
than 128k, but it is definetely not a real way to code. Can someone
explain how to fight heap corruption and memory alignment problems?
(This is the cause, as I understood from error messages). Thx to all
and sorry for poor english please ;)
 
Ad

Advertisements

J

jfbode1029

Hi to all!

I have a strange problem with malloc(). I'm writing a 2D Game Engine,
for learning purposes, and I can't go forward without understanding
the problem... So I have a function:

Sprite* CreateSprite(char *filename);

which accepts a string containing a path to an image (PNG file for
example) and returns a pointer to a struct "Sprite". Nothing complex,
Sprite is a simple typedef for SDL_Surface structure, which is used to
represent surfaces in SDL (a multimedia library), and my function uses
IMG_LoadImage() for data loading. The problem is, when I load some
images (5-6 for example) with a variable size, say from 75k to 500k,
at sixth call of CreateSprite() my program exits with malloc error
message (heap corruption, or something like this). I'm usually
programming in Linux, but the problem persists in windows too. I found
a "solution" to split images in smaller tiles, that aren't greater
than 128k, but it is definetely not a real way to code. Can someone
explain how to fight heap corruption and memory alignment problems?
(This is the cause, as I understood from error messages). Thx to all
and sorry for poor english please ;)

It would help to see the actual code, or a representative sample that
exhibits the same symptoms. Based on your description, I'm willing to
bet that you aren't allocating as much memory as you think you are,
but without seeing the actual code that's nothing more than a guess.
 
L

lndresnick

Hi to all!

I have a strange problem with malloc(). I'm writing a 2D Game Engine,
for learning purposes, and I can't go forward without understanding
the problem... So I have a function:

Sprite* CreateSprite(char *filename);

which accepts a string containing a path to an image (PNG file for
example) and returns a pointer to a struct "Sprite". Nothing complex,
Sprite is a simple typedef for SDL_Surface structure, which is used to
represent surfaces in SDL (a multimedia library), and my function uses
IMG_LoadImage() for data loading. The problem is, when I load some
images (5-6 for example) with a variable size, say from 75k to 500k,
at sixth call of CreateSprite() my program exits with malloc error
message (heap corruption, or something like this). I'm usually
programming in Linux, but the problem persists in windows too. I found
a "solution" to split images in smaller tiles, that aren't greater
than 128k, but it is definetely not a real way to code. Can someone
explain how to fight heap corruption and memory alignment problems?
(This is the cause, as I understood from error messages). Thx to all
and sorry for poor english please ;)

Hard to debug your program without lots of code.

Heap corruption can often readily be identified using tools that are
platform specific. For example Valgrind is available for linux and is
free. Rational Purify is available for both linux and Windows but
costs money. libc has an environment variable MALLOC_CHECK_ that can
be helpful in certain circumstances (e.g. duplicate free calls). If
you have questions about those comp.unix. programmer is probably the
place to go.

-David
 
V

voidexp

Ok, so this is a piece of code:

File: sprite.h

typedef SDL_Surface Image;

typedef struct
{
int x; // x position
int y; // y position
Image *surf; // A pointer to SDL_Surface
int priority; // Drawing priority (low is drawn
first, eg. in background)
} Sprite;

File: sprite.c

Image *LoadImage(char *filename)
{
Image *img = NULL;

img = IMG_Load(filename);
if(!img)
{
printf("Couldn't load image '%s'\n", filename);
exit(1);
}

return img;
}

Sprite *CreateSprite(char *filename)
{
Image *surf = NULL;
Sprite *sprite = NULL;

surf = LoadImage(filename);

// allocate memory for sprite
sprite = malloc(sizeof(Sprite));

sprite->surf = surf;
sprite->x = 0;
sprite->y = 0;
sprite->priority = DRAW_PRIORITY_NORM;

printf("Created sprite: 0x%x\n", sprite);

return sprite;
}

Since I saw that C standard allows mixing C and C++ comments, I've
started to use them, but the code is in C ;)
 
L

lndresnick

Ok, so this is a piece of code:

File: sprite.h

typedef SDL_Surface Image;

typedef struct
{
    int             x;          // x position
    int             y;          // y position
    Image           *surf;      // A pointer to SDL_Surface
    int             priority;   // Drawing priority (low is drawn
first, eg. in background)

} Sprite;

File: sprite.c

Image *LoadImage(char *filename)
{
    Image *img = NULL;

    img = IMG_Load(filename);
    if(!img)
    {
        printf("Couldn't load image '%s'\n", filename);
        exit(1);
    }

    return img;

}

Sprite *CreateSprite(char *filename)
{
    Image *surf = NULL;
    Sprite *sprite = NULL;

    surf = LoadImage(filename);

    // allocate memory for sprite
    sprite = malloc(sizeof(Sprite));

    sprite->surf = surf;
    sprite->x = 0;
    sprite->y = 0;
    sprite->priority = DRAW_PRIORITY_NORM;

    printf("Created sprite: 0x%x\n", sprite);

    return sprite;

}

Since I saw that C standard allows mixing C and C++ comments, I've
started to use them, but the code is in C ;)

I'd try Valgrind or something. I don't see anything obviously wrong
with that code, though:
1) you should check return of malloc just to be safe
2) I don't know how the memory returned by IMG_Load is allocated/
released/managed, but that could be your problem?

-David
 
V

voidexp

IMG_Load(*) is a part of SDL extension called SDL_image. It is
opensource-licensed under LGPL, so I've examined the source related to
loading PNG files, and it seems that it uses malloc() as well... :)
I've noticed another thing, running executable through gdb on linux
and Dev-C++'s debugger on windows avoides crashing (not completely,
there's a random crash each 10 runs). Reading malloc() man page, I
discovered a variable, MMAP_THRESHOLD, that deals with some sort of
limits... Does anyone know something about it's use? If someone has
free time, I can upload somewhere a tarball with entire engine and a
simple game built around it... Thx ;)
 
Ad

Advertisements

L

lndresnick

IMG_Load(*) is a part of SDL extension called SDL_image. It is
opensource-licensed under LGPL, so I've examined the source related to
loading PNG files, and it seems that it uses malloc() as well... :)
I've noticed another thing, running executable through gdb on linux
and Dev-C++'s debugger on windows avoides crashing (not completely,
there's a random crash each 10 runs). Reading malloc() man page, I
discovered a variable, MMAP_THRESHOLD, that deals with some sort of
limits... Does anyone know something about it's use? If someone has
free time, I can upload somewhere a tarball with entire engine and a
simple game built around it... Thx ;)

I'd suggest instead that you install valgrind and run it.

My question about IMG_Load was whether you disposed of the handle you
were given in whatever way you are supposed to for the associated
resources to be recovered. As opposed to, say, calling free on it.

-David
 
C

CBFalconer

It would help to see the actual code, or a representative sample
that exhibits the same symptoms. Based on your description, I'm
willing to bet that you aren't allocating as much memory as you
think you are, but without seeing the actual code that's nothing
more than a guess.

It may not be that easy. Any wild memory access, or any misuse of
the malloc/free/realloc facility, can cause that sort of error.
You will probably need to spend a lot of time checking everything.
 
A

Antoninus Twink

It may not be that easy. Any wild memory access, or any misuse of
the malloc/free/realloc facility, can cause that sort of error.
You will probably need to spend a lot of time checking everything.

Gee, if only someone would invent an automated tool for that! It would
be really great, and you wouldn't need to spend a lot of time checking
everything any more!

Who knows, maybe they could call it Electric Fence. Or Memwatch. Or
mpatrol. Or valgrind.

Or what about if compiler vendors included such functionality in their C
libraries? That would be just swell. If gcc ever did that, I'd vote for
them to call it mtrace.

Falconer, you're a living joke.
 
F

Flash Gordon

IMG_Load(*) is a part of SDL extension called SDL_image. It is
opensource-licensed under LGPL, so I've examined the source related to
loading PNG files, and it seems that it uses malloc() as well... :)

It is unlikely to be getting it wrong, although anything is possible.
I've noticed another thing, running executable through gdb on linux
and Dev-C++'s debugger on windows avoides crashing (not completely,
there's a random crash each 10 runs).

That is a not uncommon result. Someone else suggested using valgrind,
that is probably a good suggestion.
Reading malloc() man page, I
discovered a variable, MMAP_THRESHOLD, that deals with some sort of
limits... Does anyone know something about it's use?

The chances of it being the cause of your problem are negligible.

You have a bug in the code you have not shown us.
If someone has
free time, I can upload somewhere a tarball with entire engine and a
simple game built around it... Thx ;)

That all depends on how big it is.

First off try valgrind as suggested. Then try looking at *all* of your
code where you are using malloc/realloc/free, then try looking at all of
the code writing in to malloced space.
 
Ad

Advertisements

B

Bartc

Ok, so this is a piece of code:

File: sprite.h

typedef SDL_Surface Image;

typedef struct
{...> } Sprite;
Image *LoadImage(char *filename)
{
Image *img = NULL;

img = IMG_Load(filename);
if(!img)
{
printf("Couldn't load image '%s'\n", filename);
exit(1);
}

return img;
}

Sprite *CreateSprite(char *filename)
{
Image *surf = NULL;
Sprite *sprite = NULL;

surf = LoadImage(filename);

// allocate memory for sprite
sprite = malloc(sizeof(Sprite));

sprite->surf = surf;
sprite->x = 0;
sprite->y = 0;
sprite->priority = DRAW_PRIORITY_NORM;

printf("Created sprite: 0x%x\n", sprite);

return sprite;
}

So you're calling CreateSprite 6 times, that calls LoadImage 6 times which
calls IMG_Load 6 times.

Do you do anything with the result of CreateSprite inbetween calls, or would
6 successive calls crash it?

What if you leave out the call to LoadImage, or IMG_Load, can you call
CreateSprite any time of times (within reason)?

What about just calling IMG_Load, or LoadImage, by itself, does that still
go wrong after a certain number of Loads?

Is it possible the memory allocated by IMG_Load or CreateSprite is
accidentally deallocated somewhere?

Do you know which malloc() call it goes wrong at? (a simple printf will show
this, if not using a debugger, as I think you said the debugger partly hides
the problem).
 
C

CBFalconer

Flash said:
It is unlikely to be getting it wrong, although anything is
possible.


That is a not uncommon result. Someone else suggested using
valgrind, that is probably a good suggestion.


The chances of it being the cause of your problem are negligible.

You have a bug in the code you have not shown us.


That all depends on how big it is.

First off try valgrind as suggested. Then try looking at *all* of
your code where you are using malloc/realloc/free, then try looking
at all of the code writing in to malloced space.

And, when (and if) that doesn't show the fault, prepare to go over
everything with a fine tooth comb. I would start the expansion by
looking for uninitialized variables. Good luck.
 
L

luser-ex-troll

And, when (and if) that doesn't show the fault, prepare to go over
everything with a fine tooth comb.  I would start the expansion by
looking for uninitialized variables.  Good luck.

I agree! Since gdb reduces the frequency of the crashes,
this is a strong indication that, somewhere in there, you're relying
on garbage.

lxt
 
V

voidexp

I've made a simple test: I've created an array of 1024 Sprite pointers
and used CreateSprite() to load the same image file (tux.png, size
~76kb) and stored their pointers into array... Worked without problems
(at Linux at least). Then I destroyed them using free(). There weren't
any crashes! I'm now testing it with Valgrind, which prints out a lot
of messagges like "Invalid write of size 1" and the Leak Summary is
very impressive: "... possibly lost: 921,600 bytes in 4 blocks".
 
Ad

Advertisements

R

Richard Bos

Antoninus Twink said:
Gee, if only someone would invent an automated tool for that! It would
be really great, and you wouldn't need to spend a lot of time checking
everything any more!

Who knows, maybe they could call it Electric Fence. Or Memwatch. Or
mpatrol. Or valgrind.

Or what about if compiler vendors included such functionality in their C
libraries? That would be just swell. If gcc ever did that, I'd vote for
them to call it mtrace.

Oh, no! Another library? Another tool? No way! Everybody knows that
there is only one tool for this job, as for every other debugging job:
gdb. Nothing else will work, but gdb will beam the solution straight to
your mind.

Richard
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top