[A5] al_get_memory_interface?
axilmar

Will there be a function 'al_get_memory_interface', so as that our libraries and programs use the memory management routines set globally with Allegro?

Matthew Leverton

Isn't that what al_malloc(), etc, are for?

axilmar

al_malloc etc are nice, but there is no way to get the functions that have been installed in Allegro and call them directly, or examine which functions have been installed.

Elias

Is it needed? If you call al_malloc instead of malloc then the allocation will use the user callback.

For more sophisticated tracking (like e.g. if you want to know if the memory is for a bitmap or a sound sample) you can't use this interface anyway.

Peter Wang

Note that those functions are provided primarily so that you can override what Allegro does (for debugging, etc.), not so much for you to use as a generic memory management interface. That is, so you can plug Allegro into something else, not plug everything into Allegro.

axilmar

I have the following use case: I want to add diagnostic output information to the current malloc and free functions Allegro uses. In order to do that, I need the pointer to the Allegro's malloc and free functions, so as that I can install my own handlers and then call the original handlers.

Without an al_get_memory_interface function, I cannot do this.

Elias

Why do you want to call the original handlers? Just do your own malloc calls (that way you can even piggyback diagnostic info to each block, if let's say you want to add checks for leaked or double-freed blocks).

axilmar

Because there may be a problem with a 3rd party malloc function installed via Allegro to which I don't have access to. If I set the allegro's malloc with my own, the 3rd party library doesn't work any more. I'd like to see what goes into and what comes out of the 3rd party library malloc function.

tobing

Sounds like a good reason to have such a function.

Thomas Fjellstrom
axilmar said:

Because there may be a problem with a 3rd party malloc function installed via Allegro to which I don't have access to.

How often does that happen? Why do you think thats even a remotely useful use case?

The majority of allegro programs will never even touch allegro's malloc functions, let alone replace them.

Elias

If we add the function, in 99.9% of cases al_get_memory_interface would simply return NULL. And otherwise return whatever you already passed to it. You can also call the function only once and before al_init (in any scenario I can think of at least) so I don't see how a third party library or addon could do that for you.

torhu
axilmar said:

In order to do that, I need the pointer to the Allegro's malloc and free functions, so as that I can install my own handlers and then call the original handlers.

Couldn't you just require the user to call your set_mem_interface function too, if they've called Allegro's? It could even take ALLEGRO_MEMORY_INTERFACE as a parameter, so they could reuse the struct they've already prepared.

axilmar

How often does that happen? Why do you think thats even a remotely useful use case?

It will be quite useful for debugging purposes. Suppose you have a memory issue...instead of using your own allocator, you take the existing malloc and free functions and replace them with ones that print out diagnostic information and call the original functions. In this way, you have the exact same behavior as before, with the addition of your diagnostic messages.

Elias said:

in 99.9% of cases al_get_memory_interface would simply return NULL.

Why wouldn't it return the currently installed functions?

Quote:

You can also call the function only once and before al_init (in any scenario I can think of at least).

No such thing is mentioned in the docs though. What will happen if I call the function al_set_memory_interface after al_init and before any allocation?

torhu said:

Couldn't you just require the user to call your set_mem_interface function too, if they've called Allegro's?

It could be possible, but it is not a good solution.

torhu

It's beginning to sound like your use case is exactly what al_set_memory_interface is for...

Thomas Fjellstrom
axilmar said:

It will be quite useful for debugging purposes. Suppose you have a memory issue...instead of using your own allocator, you take the existing malloc and free functions and replace them with ones that print out diagnostic information and call the original functions. In this way, you have the exact same behavior as before, with the addition of your diagnostic messages.

Indeed. When you want to replace the malloc functions, just do it. Since allegro by default uses libc's malloc/free should there not be an interface setup, you need not worry about which its using. Just wrap libc's functions with your own, and call al_set_memory_interface with a table of your wrappers.

This is exactly what it was intended for.

Elias
axilmar said:

Why wouldn't it return the currently installed functions?

Usually none are installed and the memory interface is just NULL (and Allegro will use the normal malloc and so on).

Quote:

No such thing is mentioned in the docs though. What will happen if I call the function al_set_memory_interface after al_init and before any allocation?

al_init also will allocate things already I think. But yes, the documentation should be clear about when the function can be called. But I doubt there's a requirement for system drivers to not use al_malloc which means they likely use it already and so the memory interface needs to be set before.

axilmar

Indeed. When you want to replace the malloc functions, just do it. Since allegro by default uses libc's malloc/free should there not be an interface setup, you need not worry about which its using. Just wrap libc's functions with your own, and call al_set_memory_interface with a table of your wrappers.

This is exactly what it was intended for.

What if I don't have access to the malloc functions?

What if I use a 3rd party library that has its own malloc functions installed via Allegro?

What if I need to override the existing malloc functions for a specific task, and then restore the originals?

Elias said:

al_init also will allocate things already I think...and so the memory interface needs to be set before.

That doesn't exclude the use case of overriding the existing behaviors for debugging purposes.

Anyway, it's not that important. If you feel it's such a burden to implement, then please ignore this request.

Elias
axilmar said:

Anyway, it's not that important. If you feel it's such a burden to implement, then please ignore this request.

It's not a burden at all - you'd be the one sending the patch anyway :) Just trying to see the use case, especially with the current behavior where the mem interface is usually just a NULL pointer. If you make the patch (including documentation) I don't see a problem applying it.

axilmar
Elias said:

you'd be the one sending the patch anyway

how can I do that?

tobing

Get allegro sources from SVN, edit your files, then create a patch file, which you then attach to a posting here or send to the allegro developers mailing list.

axilmar
tobing said:

Get allegro sources from SVN, edit your files, then create a patch file, which you then attach to a posting here or send to the allegro developers mailing list.

Wouldn't be easier if one of the developers added the function? it's just one simple function with the most trivial implementation there is: copy the internal memory interface structure to the one given in the parameter. Here it is:

void al_get_memory_interface(ALLEGRO_MEMORY_INTERFACE *ami) {
    assert(ami);
    if (mem) {
        *ami = *mem;
    } else {
        ami->mi_malloc = NULL;
        ami->mi_free = NULL;
        ami->mi_realloc = NULL;
        ami->mi_calloc = NULL;
    } 
}

By the way, I noticed the following in the ALLEGRO code:

  • the ALLEGRO_MEMORY_INTERFACE pointer passed to the function 'al_set_memory_interface' is kept by the Allegro library. Wouldn't it be better if the library kept a copy of the struct? the docs do not say that the ALLEGRO_MEMORY_INTERFACE struct must not be allocated on the stack.


  • the memory interface functions have an 'if' in them: 'if (mem) ...'. Wouldn't it be better if the 'if' was skipped, the internal ALLEGRO_MEMORY_INTERFACE struct was setup to point to the appropriate functions, and those functions called the default libc implementations? the 'if' could be skipped.

tobing

I guess just adding this function is the easy part. What about testing and adding appropriate documentation?

Edit: Maybe I'll look into this during the weekend. No promise, though.

axilmar
tobing said:

Edit: Maybe I'll look into this during the weekend. No promise, though.

Thanks a lot everyone.

tobing

Here's a patch, adding two functions: al_get_memory_interface, and al_get_default_memory_interface. Wasn't too difficult after all.

Ron Novy

Why not make a generic add-on library for debugging memory? Then in most cases there would be no reason for anyone to use those new functions. They would instead use the add-on library interface. You could then debug everything that uses al_malloc(); and get whatever information you need...

Not sure if this is relevant, but something I did a while back for debugging in windows was to create a header file that would override all libc functions that allocated, reallocated or freed memory (but I may have missed some). As long as the header file was included after all other header files it captures all allocations of memory...

It would put everything into a sort of garbage collector. If the program exited without freeing all the allocated memory then it would dump a list of each leak. The dump included the source file and line where it was allocated, the size in bytes and even a short memory dump of each memory leak.

It's a crude hack for a specific project/purpose, but I attached it in case it inspires anyone... May need a little modification to work for you, like removal of cbuf/fifo stuff, but it should work should you decide to hack it...

Just define these in leak.c and it should compile

// Also comment these out!
//#define INCLUDE_FIFO
//#include "ucode/cbuf.h"


#define OMF_DEBUG_FILE_NAME "omfdebug.txt"
#define DLL_EXPORT
#define DEBUG_LEAKS
#define REMOVE_ON_FREE
#define FREE_LEAKS

Then add 'atexit(debug_atexit);' in your 'main()'.

Arg... I must be bored...

Thread #606268. Printed from Allegro.cc