Object size limit within Max/MSP ?
I am facing a very weird behaviour in Max/MSP for an external I am writing. This external contains a DSP engine with a wavetable.
The external crashes (or makes Max/MSP crash – it crashes sometimes when my external function returns to Max/MSP) with a "BAD_ACCESS" error, each time my code tries to write within the wavetable (of course, I checked the pointers, they are ok)
The strange thing is that it crashes only when the DSP engine is allocated statically within the MSP object structure
typedef struct _MaxOctos
t_pxobject ob; // the object itself (t_pxobject in MSP)
float SFreq; // Sampling frequency
TOCTOS_ENGINE Engine1; // CRASH IF I WANT TO ACCESS THE WAVETABLE IN THIS OBJECT !!!!
TOCTOS_ENGINE* Engine2; // ACCESS TO WAVETABLE WORKS (after allocation in object_alloc of course...)
If I just change the Engine definition (becoming a pointer) and allocate Engine in the new() method after object_alloc, everything works fine.
The size of the t_MaxOctos object changes from 1.5Mbytes to 40 bytes only when I use dynamic allocation, that’s the only change I can see.
I would be extremely surprized that Max can not deal with a 1.5MB structure, but honnestly I can not find any explanation in my code for this (I stripped almost everything from my code, just to make sure that it crashes when I access the "big" wavetable – I even stopped the DSP processing).
However, since using dynamic allocation seems to work, I prefer to ask here if such a memory limitation exists.
It’s not Max, but your C compiler. Stack allocation has very rigid limitations, due to the very nature of the allocation mechanism itself.
AFAIK the maximum size of stack-allocated memory is implementation-dependent, on gcc 32-bit it should be 16k (but someone please correct me if I’m wrong). In any case, you’ll never be able to allocate Mbs on the stack.
So, whenever you have wavetables or big arrays or things like that go for heap allocation and don’t look back!!!
… ok, so it’s probably 32k… ;)
Hi Andrea — Valid point, except Max objects are allocated on the heap. (I can’t honestly think of any exception where a Max object is on the stack, but there probably is some rare case out there I’m forgetting).
As to Ben’s problem, Nicolas is on the right track. Max objects are normally allocated by getbytes(), which traditionally had a limit of 32kB (actually, just 4 bytes shy of that limit). With Max5 or 6 the limit may have been lifted, but I think at most to 64k. I would advise consulting the documentation before relying on anything more than 32k. For what Ben’s trying to do, it is absolutely mandatory to allocate larger blocks of memory with the OS-native API, typically malloc() & friends. This is, btw, covered in the SDK tutorial.
For multi-MB allocation you really do need to test that the memory was allocated (ie, alloc() did not return NULL) and handle the failure gracefully. Otherwise you will crash Max, and that’s such an ugly thing to do. Remember, if Max crashes while your external is running, it’s your fault. Not Max’s.
Finally, don’t forget that you have to free memory with calls from the same API you used for allocation (d’uh). Allocating with malloc() and then using freebytes() on the block is one of the most inane ways possible of crashing.
Thank you for the answers. I was not aware of this 32 KB limit per Max object.
I will use a heap allocation scheme for the DSP processing object (by the way, I did not blame Max for crashing, Peter. I was sure that my external was the source of the problem, by corrupting something in Max memory)
Concerning the stack size problem, I do not agree with your values Andrea. Maximum stack size depends on the compiler settings, that’s true, but it’s much more than 32Kb (it was already 64Kb in x86 in real mode = one memory segment)
As far as I remember, it’s something around 1 or 2 Mb with gcc32 and MSVC nowadays
Anyway, since Max objects are not allocated on the stack…
omg, sorry for the nonsense! of course Max objects are heap-allocated…
otoh, I still might be wrong but I’m afraid that one thing is the stack size itself, one thing is how much memory you’re allowed to claim in a single stack frame… not sure, but I think I have experienced that…
… but I’m feeling sleepy today, so don’t get mad at me if all this is more nonsense ;)