Skip to main content
gamedev.net
🔒 Locked

realloc returns zero

Started by ProPuke Jan 11, 2005 at 9:11 PM 14 replies 1.9k views
Original Post
ProPuke
ProPuke
Debugging a memory manager. I did a full listing of all allocations resizes & destructions. Finally the problem became apparent - a resize on a memory block(realloc()) returns zero The block being worked on is allocated & is resized once before this happens. but upon the second resize the returned address is zero. & shortly after, this unhandled event causes a rapid demise to the program in question. The fact that the address fed into the first resize was recorded as being allocated & the address exiting this resize is the same one entering the next suggests that the memory address in question should be nice clean allocated space. I realise that realloc does return 0 upon failure but we're talking an allocation of 24 then 32 bytes so it ain't like my machine is starved for ram. I fear I know the answer but is this a natural phenomenon of realloc to return a 0 that must be handled now & then, or is it, as I fear, a corruption on the stack somewhere or some unaccounted free etc of the area of memory. I've been going over it with a fine tooth comb (whatever) & nothing else apparently wrong has shown. Still waiting for that sudden spark of realisation as to what the problem is but in the meanwhile a straight answer or prehaps some words of experience might help ty
____ _ ___ ___ __ _`By offloading cognitive load to the computer, programmers are able to design more elegant systems' - Unununium OS regarding Python
PnP Bios
PnP Bios
Don't use realloc.
1) create a new chunk of memory
2) memcopy the old chunk to the new one
3) delete the old one
4) reassign the pointer
ProPuke
ProPuke
No explanation, just an unhelpfull order.
I wish to get around this problem not avoid it (I may avoid it after but that's beyond the point). I also wish to use realloc. I was under the impression that resizing blocks was vastly faster than full reallocation.
ty for your opinion. Any others?
____ _ ___ ___ __ _`By offloading cognitive load to the computer, programmers are able to design more elegant systems' - Unununium OS regarding Python
Raduprv
Raduprv
If you didn't do it yet, print the variables used to alloc and realloc in a file, just before the function calls, to see if they are ok.
And BTW, the lounge is not the best forum for this question.
ProPuke
ProPuke
Yeah sorry I just realised that I had posted in the lounge. if this could be moved It would be appreciated, otherwise sorry.
Not sure what you mean by print the variables. I'm listing the addresses of everything worked upon by the memory unit though. the address being passed to realloc is fine according to the best of my knowledge
____ _ ___ ___ __ _`By offloading cognitive load to the computer, programmers are able to design more elegant systems' - Unununium OS regarding Python
choffstein
choffstein
Can we see your initialization and realloc code? I am suprised realloc is returning null on such a small reallocation -- it shouldn't have any problem finding a chunk of memory that large in memory, unless you have already soaked up everything else.

Raduprv
Raduprv
Well, aren't you using some variables in the function call, like original address, and the size? Just print them before calling the function, to make sure they are right. Some buffer overflows can corupt your local/global variables.
ProPuke
ProPuke
That is exactly what I have done, I've told you what I've seen. a failure upon an allocation of 36 bytes to an address returned by a previous resize. I've followed all the printed address through & they link in okay to allocations. also all the sizes are in check.
The memory unit is large to say the least, & very templated. But eventually all calls rely on 3 base functions: an allocator (malloc) routed through a new operator, a resize method (realloc) & a deallocator (free) with manual dtor calling. in the meanwhile all of these are kept track of in a allocation list to perform address checking & perform garbage collection. but all calls that effect go through these 3 methods & these are the only that effect the memory itself.
They are giving full output on all effected addresses so I am seeing everything that is happening as an end result. I'm afraid I can't show you. I know something is catching me out & I don't expect anyone else to be able to work it out unless they've spent a few weeks studying the whole thing. But I am looking for suggestions. any reasons that would cause a rogue failure of realloc?
I guess it is too much to ask this. A few more weeks of sweat over it & I may solve it (or die), but it looks like I'm going to have to do it on my own hide
____ _ ___ ___ __ _`By offloading cognitive load to the computer, programmers are able to design more elegant systems' - Unununium OS regarding Python
Raduprv
Raduprv
Quote:
[...]an allocator (malloc) routed through a new operator[...]

What exactly do you mean by that? You don't allccate the memory with new, and then resize it using realloc, right?
ProPuke
ProPuke
Morning all
Quote:
Quote:
[...]an allocator (malloc) routed through a new operator[...]
What exactly do you mean by that? You don't allccate the memory with new, and then resize it using realloc, right?

No, I allocate the memory using malloc & a ctor is called by passing it through a new operator. It's custom created ofcourse (just an empty placement new)

And no, I'm not using vc6 :/

But thanks anyway everyone for your time
____ _ ___ ___ __ _`By offloading cognitive load to the computer, programmers are able to design more elegant systems' - Unununium OS regarding Python
flure
flure
Quote:
Original post by PnP Bios
Don't use realloc.
1) create a new chunk of memory
2) memcopy the old chunk to the new one
3) delete the old one
4) reassign the pointer


Why not use realloc ? You just say that because you don't know how to use it !!
realloc works like this :

/* p is the pointer (of type p_type) that we want to reallocate */p_type* temp = NULL;temp = realloc (p, new_size);if (temp==NULL) { free (p); handle_error_and_quit ();}p = temp;
--flurehttp://flure.free.fr
Anon Mike
Anon Mike
You can try to hack your way around this particular realloc failure or you may discover some sort of corruption that is causing this but in the end...

Quote:
but is this a natural phenomenon of realloc to return a 0 that must be handled now & then


yes, it is quite natural for realloc to fail. The fact that you're asking for a small amount of memory is irrelevant. Eventually you'll either run out of memory or fragment your heap so bad that an alloc of 0 bytes will fail.

If you think there is a possibility of heap corruption that is causing this then search your compiler docs for heap validation functions.

Quote:
I was under the impression that resizing blocks was vastly faster than full reallocation


Only if you're decreasing the size of the memory block or you get lucky and there is a free adjacent block big enough to hold the increased size and your compiler libraries even bother to try to do this. realloc can easily be worse than malloc if you end up copying the original memory needlessly.

Using realloc heavily can also make heap fragmentation worse that it otherwise would be which will make your memory problems bigger.
-Mike
choffstein
choffstein
Quote:
Original post by Anon Mike
yes, it is quite natural for realloc to fail. The fact that you're asking for a small amount of memory is irrelevant. Eventually you'll either run out of memory or fragment your heap so bad that an alloc of 0 bytes will fail.


Heap fragmentation would have to be pretty horrendous not to be able to allocate 32 bytes. If you are using so much memory that a consecutive 32 bytes cannot be located in memory...well, then ... the issue may be greater than simple reallocation.

Try looking into a memory pool, where you initiate 1000 instances of the object, and then when requesting a new one, you just return a pointer to it, so that your memory is less fragmented. Anyway to cut down on nonconsecutive malloc()s and free()s would help.
flure
flure
Quote:
Original post by Anon Mike
You can try to hack your way around this particular realloc failure or you may discover some sort of corruption that is causing this but in the end...


I think the bug should come from posterior memory leaks. The original poster should track them with a specialized tool, as Valgrind for example.

Quote:
Original post by Anon Mike
Quote:
but is this a natural phenomenon of realloc to return a 0 that must be handled now & then


yes, it is quite natural for realloc to fail.


realloc fails when it doesn't find enough space for the new block. But, when it fails, the original pointer is still valid !
That's why, to avoid bugs, realloc should be used with a temporary pointer (see my above post).

Quote:
Original post by Anon Mike
The fact that you're asking for a small amount of memory is irrelevant. Eventually you'll either run out of memory or fragment your heap so bad that an alloc of 0 bytes will fail.


He should have to do millions of allocations to stumble upon such a problem. I think the bug is elsewhere.

Quote:
Original post by Anon Mike
Quote:
I was under the impression that resizing blocks was vastly faster than full reallocation


Only if you're decreasing the size of the memory block or you get lucky and there is a free adjacent block big enough to hold the increased size and your compiler libraries even bother to try to do this. realloc can easily be worse than malloc if you end up copying the original memory needlessly.


That happens less than you think. The original poster IS right, realloc is faster. If it finds enough bytes just after the already allocated block, it just has to "extend" the pointer, instead of copying it elsewhere. And this is the most common case.

Quote:
Original post by Anon Mike
Using realloc heavily can also make heap fragmentation worse that it otherwise would be which will make your memory problems bigger.


Excuse me, but ... bullshit.
As I said above, realloc will try to extend the block. Using a newly created pointer and copying from the source will NOT do that optimisation, thus fragmenting EVEN MORE than realloc.
Maybe you should google on "man realloc" before posting such misinformation.
--flurehttp://flure.free.fr
Anon Mike
Anon Mike
pattern #1
----------
alloc 1000 bytes
alloc 1000 bytes again
decide 1000 is to many so alloc 990 bytes
free allocation #1
- result is one nice big free block to play for the next 1000 byte allocation

or

pattern #2
----------
alloc 1000 bytes
alloc 1000 bytes again
decide 1000 is to many so realloc allocation #1 to 990 bytes
- result is one useless 10 byte fragment.


I've seen apps that did pattern #2 over and over and over killing thier heap. There's no misinformation here. It's ten years experience debugging third party code.

My point when I said realloc can fail is that it sounds very much like the original poster is trying to come up with an excuse to avoid handling failures. "small" allocations *can* fail. Yes it's unlikely and is very likely an indication of a memory leak elsewhere or something but ignoring the possibility of failure will only cause him grief.
-Mike

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.