Array Within Object's Struct Causing Crash

    Apr 02 2009 | 9:18 pm
    So I was having trouble with my code, where basically I am determining the size of a buffer (which is just an array within my object's structs) in samples, then recording into that buffer and then playing back from that buffer (eventually I would like to be able to manipulate the playback in certain ways, but first I just want to be sure it can playback). However, whenever I tried to record into the array ( x->t_buff[index] = *in++ ), max would crash.
    I thought it might have to do with the dynamic memory allocation I have for determining my buffersize, so I tried to make my buffer a fixed length. However, when I had a buffer of a fixed length within my object's struct, Max would crash as soon as I tried to create the object (it would crash on the first line of the new method, during my newobject() call).
    I've included my code for both the code that doesn't have an array in its struct, and only uses dynamic memory allocation, and the code that has the array. Please let me know what the problem could be.
    Much thanks for any help.

    • Apr 02 2009 | 9:35 pm
      1. Object struct max size is 32k, which is most likely why your static array version crashes.
      2. getbytes max size is also 32k, which is most likely why your dynamic array version crashes. Use t_getbytes/t_freebytes or sysmem_newptr/sysmem_freeptr instead.
    • Apr 02 2009 | 11:53 pm
      thanks for the info, josh. ill try using those other functions instead of getbytes.
    • Apr 04 2009 | 1:52 pm
      jkc - i am using sysmem_newptr/sysmem_freeptr (wasn't able to find mention of t_getbytes or t_freebytes in the SDK documentation for Max 4 (writing for Max 4 currently, btw)) and it works beautifully. Except when I try to deallocate memory while the buffer is being read from, in which case I often get a bad access error. I tried to circumvent this by creating a "pause" variable within my object's struct, where the part of my dsp perform function that reads from the dynamically allocated memory can only be executed if (x->pause == 0). So when deallocating memory, I first set x->pause = 1; then once its been allocated, I set x->pause = 0; however, I am still getting bad access errors. do you know how I might overcome this? Attached is my code.
    • Apr 05 2009 | 1:02 am
      In rhythmgran_perform(), I would check to see if your buffer index is within bounds before setting/accessing a buffer value.
      WRT x->pause, I don't think that's sufficient protection because rhythmgran_perform() and createbuffer() will be called in separate threads. You should do some research on multithreaded programming. Or you could use one buffer big enough to accommodate the most likely buffer sizes. That way, you don't have to worry about creating/freeing buffers except in your new() and free() methods.
      The Max5 SDK has some thread protection stuff built in, but I'm unclear as to whether they work in the audio thread. Of course, you could always use 3rd party tools like pthreads.
    • Apr 05 2009 | 6:05 pm
      Thanks for the reply Davis.By initializing my x->index to 0 in the new function, and then having the if(index >= buffersize) index = 0 statement in my perform method, isn't that checking the bounds of index? If not, I'm not entirely sure what it is you mean. Could you perhaps post a few lines of sample code to illustrate your point?
      Good point on multithreading. For now, I'll probably just allocate X amount of memory and not let the buffersize exceed that. Thanks for the suggestion.
    • Apr 05 2009 | 7:59 pm
      What I meant was that you have this line:
      x->t_buff[index] = *in++;
      before this line:
      if(index >= buffersize) index = 0;
      in your perform function. I'm not familiar with the details of your code, but as a general rule it's just not a good idea.
    • Apr 05 2009 | 8:32 pm
      Ah, I see. That makes sense. Thanks for the tip.