28 July 2020, 08:32 | #1 |
Registered User
Join Date: Oct 2015
Location: Landsberg / Germany
Posts: 526
|
AllocVec returning zero - why?
Hi guys!
Working on RESHOOT PROXIMA 3 for some months now. From time to time, the executable fails and returns to WB, because AllocVec returns 0 in d0-register. The values in d0 and d1 given to the function are all fine and there is plenty of free memory. Happens at different sections of the game, here and there. Code is pretty straightforward: Code:
move.l #copperGameMaxSize,d0 ; copperlist max. size move.l #Chip!Mem_Clear,d1 CALLDOS AllocVec tst.l d0 beq .noMemory ... CALLDOS MACRO move.l Execbase,a6 jsr _LVO\1(a6) ENDM |
28 July 2020, 08:55 | #2 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
Hmm, I'd save d1 prior to allocvec, restore immediately after and on fail call availmem and examine d0
|
28 July 2020, 09:16 | #3 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
|
If AllocVec returns zero, then not enough memory. I don't see any other reason.
There could be plenty of memory overall but not enough chipmem. It is possible total is enough but memory is fragmented. Typing availcommand could give more info. |
28 July 2020, 09:23 | #4 |
Registered User
Join Date: Mar 2012
Location: Norfolk, UK
Posts: 1,153
|
Where you do define Chip and Mem_Clear? (I though the official includes call them MEMF_CHIP and MEMF_CLEAR, respectively?)
Make sure you're using the flag definitions, not the bit definitions. i.e. flag is (1<<bit) |
28 July 2020, 11:09 | #5 |
Semi-Retired
Join Date: Mar 2012
Location: Leiden / The Netherlands
Posts: 1,993
|
Even if defined correctly, not sure if you wanted ! instead of |
|
28 July 2020, 12:00 | #6 |
Registered User
Join Date: Oct 2015
Location: Landsberg / Germany
Posts: 526
|
Defs look like this
Code:
MEMF_ANY = 0 MEMF_CHIP = 1<<1 MEMF_FAST = 1<<2 MEMF_CLEAR = 1<<16 MEMF_TOTAL = 1<<19 Used Debugger to check that move.l #Chip!Mem_Clear,d1 or move.l #Chip|Mem_Clear,d1 both translate to MOVE.L #$00010002,D0 Which should be fine. |
28 July 2020, 12:28 | #7 |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
Where/how is "copperGameMaxSize" defined?
|
28 July 2020, 12:51 | #8 |
Registered User
Join Date: Mar 2012
Location: Norfolk, UK
Posts: 1,153
|
Is it a fragmentation issue?
If you're randomly allocating and freeing larger numbers of memory chunks, and not freeing them in reverse order of allocation, you could end up without a large enough contiguous chunk to satisfy an allocation. Also, could you be overrunning an allocation and corrupting the memory lists? (I don't know exactly where AllocVec stores the size that's been allocated, but if I had to guess I'd say immediately before or immediately after the allocated chunk.) |
28 July 2020, 13:05 | #9 | |
Registered User
Join Date: Oct 2015
Location: Landsberg / Germany
Posts: 526
|
Code:
copperGameMaxSize = 10500&$fff8 ; align to size of 8 Quote:
Also, yes, corruption of memory lists might be the case. But the game does compare free memory at the very start and very end of startup, and throws an error if both numbers are not the same. Implemented this to identify memory leaks. If pointers / size markes are overwritten within game code, should this not result in memory leaks? |
|
28 July 2020, 13:20 | #10 |
Registered User
Join Date: Sep 2019
Location: Leicester / England
Posts: 201
|
Do you need to keep allocating and freeing the memory?
Could you allocate it all at the beginning, use it when necessary, then free it at the end when exiting, thus preventing fragmentation? |
28 July 2020, 13:32 | #11 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,215
|
Sounds more like an issue of a bad pointer, damaging memory and hence the freelist of exec. MuGuardianAngel may be helpful to hunt down the issue.
BTW, I think it is a bit strange to call a macro CALLDOS, which actually calls exec. Not dos. |
28 July 2020, 14:33 | #12 | |
Registered User
Join Date: Oct 2015
Location: Landsberg / Germany
Posts: 526
|
Quote:
True. Did that macro years ago and stuck with it. Changed it right now. |
|
28 July 2020, 14:39 | #13 |
Registered User
Join Date: Oct 2015
Location: Landsberg / Germany
Posts: 526
|
Well... I do most memory allocation like that, and de-alloc / re-alloc one memory chunk only when switching between stages. Should not cause too much fragmentation.
|
28 July 2020, 14:48 | #14 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,215
|
|
28 July 2020, 20:48 | #15 | |
Going nowhere
Join Date: Oct 2001
Location: United Kingdom
Age: 50
Posts: 8,986
|
Quote:
Will likely fix your memory issues. |
|
28 July 2020, 21:37 | #16 | |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
|
Quote:
If your copper list can grow to 10500 bytes, you need to round up: (10500+7)&fff8 Considering you didn't mention any memory list-related gurus, I suspect memory fragmentation as well.. Last edited by hooverphonique; 28 July 2020 at 21:52. |
|
28 July 2020, 22:45 | #17 | |
Registered User
Join Date: Oct 2015
Location: Landsberg / Germany
Posts: 526
|
Quote:
Guys, thanks a lot for inspiration. Will keep you posted! |
|
19 September 2020, 22:40 | #18 |
Registered User
|
Memory allocation can also fail if the memory list gets damaged.
Depending on the damage done, largest free memory block can shrink dramatically. I have experienced largest free blocks suddenly dropping down from 98% to less than 10% of total memory, just because of memory corruption (actual memory allocated and used was in few KB range). If in doubt, consider C:AVAIL it will show both free and largest free! Accidentally overwritten memory is really evil!!! |
21 September 2020, 01:02 | #19 |
Registered User
Join Date: Oct 2015
Location: Landsberg / Germany
Posts: 526
|
I established a number of checks in "debug mode" which should make sure that I get notifications in case unallocated memory gets written to. Had no more strange memory alloc errors any more since then.
|
21 September 2020, 04:17 | #20 |
Registered User
Join Date: Dec 2019
Location: Newcastle
Posts: 67
|
While allocating all the memory you require in one go does make life easier to manage memory, It relies on the fact that no other running application has memory allocated. Even a small application can have allocated ram that splits up the largest memory block, this is sadly the hazard of non paged memory.
So allocating in blocks that you require may still find blocks of adequate size, where allocating the full amount is highly likely to fail, if not called right after a clean boot. AllocVec will allocate an extra memory block chunk (I believe this is 8 bytes) for the memory details followed by the required memory. This makes it easy for FreeVec() to verify the block, by simply moving back one block ( Same as modern PC based memory heaps work) When Memory is freed, the first block is used as a node for the free memory list (Size and Next pointer). If this memory is written to after freed it will destroy the free memory list. Though I would suspect that they would have to be zeroed, as any other data would most likely result in a crash. If the allocated memory block is altered, i.e a negative offset writing over the information block, this would cause the FreeVec() function to free an incorrect amount of memory. You could check this size in the info block before freeing to see if this has been overwritten. |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Returning to Amiga. | shoestring | New to Emulation or Amiga scene | 3 | 13 June 2020 05:13 |
Returning Amigan | willbloke | New to Emulation or Amiga scene | 8 | 18 April 2017 11:47 |
Returning to Amiga after 25 years ... | hedders | New to Emulation or Amiga scene | 17 | 07 May 2015 23:00 |
Another one returning | GarethPW | Member Introductions | 5 | 06 July 2011 13:14 |
Returning to Amigas - new to emulation | antonvaltaz | Member Introductions | 9 | 19 May 2009 12:02 |
|
|