Welcome, Guest. Please login or register.

Author Topic: AllocMem/AllocAbs/FreeMem()  (Read 2237 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline nyteschaydeTopic starter

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 643
    • Show only replies by nyteschayde
    • http://www.nyteshade.com
AllocMem/AllocAbs/FreeMem()
« on: January 11, 2017, 12:27:16 AM »
So looking at the AllocMem/AllocAbs/FreeMem methods in Amiga exec, I noticed that it requires you to keep track of how much memory to free when the time comes to do so. What are the most common ways that you do this? Do you use an exec List to track it? A global variable?

It seems the advantage is that AllocMem takes a request on which type of RAM you are asking to allocate from (CHIP, FAST, 32BIT, etc...). What is the difference in using the exec memory functions over the standard C ones like malloc/calloc/realloc and so on?

Additionally, using the Amiga paradigm, if I wanted to implement a ReAllocMem() function, I presume a few things would have to be done in order do this.

1. Try using AllocAbs() to get the additional memory immediately after the memory allocated with AllocMem().
2. If unavailable, do an AllocMem() for the total size desired and copy the memory from the original location to the new one. Finally, freeing the old one.
3. Return NULL if there was no chance to allocate the full new block in step 2.

Should I go through all this trouble? Why should I use the exec memory functions over the C memory functions? Are there any performance benefits to doing so? What about any other unintended side effects of not using the Amiga Exec routines?
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

Online Thomas

Re: AllocMem/AllocAbs/FreeMem()
« Reply #1 on: January 11, 2017, 03:55:22 PM »
Actually AllocAbs should never be used and instead of AllocMem/FreeMem you should use AllocVec/FreeVec.

If properly implemented, the C memory functions should use memory pools and thus are preferable over the system functions. You need AllocVec only if you want to allocate memory with specific attributes. Or if you want to implement a C runtime library ;)

IIRC the addresses returned by AllocMem and AllocVec are always aligned to 64 byte boundaries. This does not necessarily apply to malloc & Co.

guest11527

  • Guest
Re: AllocMem/AllocAbs/FreeMem()
« Reply #2 on: January 11, 2017, 03:57:20 PM »
Quote from: nyteschayde;819489
So looking at the AllocMem/AllocAbs/FreeMem methods in Amiga exec, I noticed that it requires you to keep track of how much memory to free when the time comes to do so. What are the most common ways that you do this? Do you use an exec List to track it? A global variable?
It depends on what you want. In some cases, the size does not need to be tracked because you know anyhow which object you allocted the memory for, so just take the size of this object when allocating it, and again when releasing it. The C "sizeof()" operator will tell you the size of an object in bytes.

In other cases, if you do not know exactly what the size was, exec has the alternative function pair AllocVec()/FreeVec() which do remember the size, so you do not need to track. (Actually, these are the tripos counterparts that were present before in Tripos and the 1.2 dos.library, and then moved into exec for 2.0).

In again other cases, you do not want to track a single individual memory allocation, but a whole bunch of them. In such cases, you're probably better off using the memory pool functions of exec. Create a memory pool, allocate memory from this pool, and release the entire pool in one step when the program is gone. No need to remember each individual allocation.

Then again, some legacy functions exist both in intuition and icon.library to track memory allocations (AllocRemember() and friends) and release them in one go. I would consider all these functions outdated, and would point you to the exec memory pools as they are more convenient to use, and do not fragment the memory as badly as the legacy functions do.


Quote from: nyteschayde;819489
It seems the advantage is that AllocMem takes a request on which type of RAM you are asking to allocate from (CHIP, FAST, 32BIT, etc...). What is the difference in using the exec memory functions over the standard C ones like malloc/calloc/realloc and so on?
malloc() in the stdlib of your compiler will track all memory for you, and will release it to the operating system when done. Specifically, calling exit() to leave your program will release all memory allocated with malloc(), but not the memory allocated with AllocMem() and the exec functions.

Whether that is what you want depends again on your application. If you want to create data structures that persist the lifetime of your program, then AllocMem() and friends is the only way to go. Otherwise, malloc() is more convenient, but has a somewhat higher overhead because it needs to be linked to your program. Your binary gets larger.

Quote from: nyteschayde;819489
Additionally, using the Amiga paradigm, if I wanted to implement a ReAllocMem() function, I presume a few things would have to be done in order do this.

1. Try using AllocAbs() to get the additional memory immediately after the memory allocated with AllocMem().
I wouldn't attempt that. In most cases, you will not be able to get this memory anyhow, and even if you do, you need to be very careful with the alignment of the memory you allocate (essentially, exec tracks memory in group sizes of 8 bytes, and you need to round properly to get exactly the memory you want), and last but not least, you violate a "golden rule", namely that each call to AllocMem() should be matched by a call to FreeMem(). While it might be in principle "ok" to allocate memory in smaller chunks and release it as one bigger chunk later, it may certainly confuse some memory tracking and debugging software (such as Mungwall or MuGa). You are operating on very "slippery" terrain. Do not try. I would call this bad programming practise.

The C stdlib contains realloc(), which is safe in general as it operates only on the internal structures of the particular implementation of the stdlib, but not on the operating system structures itself.

One general rule: The need to use realloc() typically shows improper use of data structures. It means that you typically need to rethink your solution, and come up with a more dynamic data structure. E.g. instead of "arrays" think "lists" or "trees", depending on the problem you want to solve.



Quote from: nyteschayde;819489
2. If unavailable, do an AllocMem() for the total size desired and copy the memory from the original location to the new one. Finally, freeing the old one.
Two problems here: a) you fragment memory overly as you leave a small chunk of memory in front of your bigger chunk unused, and b) any pointer that pointed into the originally allocated memory will be invalidated.

Hence, it only works in simple cases where we only have arrays, but no pointers into the array, and even then it is poor programming practise. Reconsider the way how you organize your data.

The solution is really to structure data in a better way and stop thinkking in "arrays and values". Fortran worked like this in the early days, but "higher data structures" are the way to go.