External works, but causes 'crashiness' in Max7.


    May 03 2016 | 10:03 am
    Hello again,
    Another probable noob style question... I have built a relatively simple external to generate low-passed random numbers (ie - skewed to the low end of a range). Nothing complicated, it takes two arguments - the range and a 'Q' value and when it receives a bang it spits out a random integer much like the native random object does. The external is working properly as far as I can tell, but it seems to be causing some amount of crashes. I had some difficulty getting it to work in the first place which was down to memory allocation issues and I suspect that may still be the problem now, but I have no idea why. the full code is as follows:
    #ifdef WIN_VERSION #define _CRT_RAND_S #endif
    // ---------- include
    #include "ext.h" #include "ext_obex.h"
    // ---------- object
    typedef struct _lprand { t_object obj; long *rndarray; long range; long q; void *out; } t_lprand;
    // ---------- function prototypes
    // standard set void *lprand_new(t_symbol *s, long argc, t_atom *argv); void lprand_free(t_lprand *x); void lprand_assist(t_lprand *x, void *b, long m, long a, char *s);
    // additional void lprand_bang(t_lprand *x); long rnum(long range); long lopass(t_lprand *x, long range, long q);
    // ---------- global class pointer
    void *lprand_class;
    // ---------- main
    void ext_main(void *r) { t_class *c;
    c = class_new("lprand", (method)lprand_new, (method)lprand_free, (long)sizeof(t_lprand), 0L, A_GIMME, 0);
    class_addmethod(c, (method)lprand_bang, "bang", 0);
    class_register(CLASS_BOX, c); lprand_class = c;
    post("lprand object instantiated."); }
    // ---------- assist
    void lprand_assist(t_lprand *x, void *b, long m, long a, char *s) { if (m == ASSIST_INLET) { sprintf(s, "Inlet %ld accepts a bang", a); } else { sprintf(s, "Outlet %ld delivers a low-passed random number.", a); } }
    // ---------- rnum (random number)
    long rnum(long range) { long rand;
    #ifdef WIN_VERSION rand_s(&rand); #else rand = random(); #endif
    rand = rand % range;
    return rand; }
    // ---------- lopass (low passed random number)
    long lopass(t_lprand *x, long range, long q) { long counter; long minimum;
    for (counter = 0; counter < q; counter++) { x->rndarray[counter] = rnum(range); }
    minimum = x->rndarray[0];
    for (counter = 0; counter < q; counter++) { if (x->rndarray[counter] < minimum) { minimum = x->rndarray[counter]; } }
    return minimum; }
    // ---------- bang
    void lprand_bang(t_lprand *x) { long rand = lopass(x, x->range, x->q);
    outlet_int(x->out, rand); }
    // ---------- free
    void lprand_free(t_lprand *x) { sysmem_freeptr(x->rndarray); }
    // ---------- new
    void *lprand_new(t_symbol *s, long argc, t_atom *argv) { t_lprand *x = NULL; long range, q;
    if (argc != 2) { post("Incorrect number of arguments for the lprand object."); return NULL; }
    range = atom_getlong(argv); if (range < 1) { post("Range argument must be greater than 1."); return NULL;}
    q = atom_getlong(argv+1); if (q < 1 || q > 10) { post("Q argument out of bounds. It must be between 1 and 10 (inclusive)."); return NULL; }
    if ((x = (t_lprand *)object_alloc(lprand_class))) { x->rndarray = (long *)sysmem_newptrclear(q);
    x->range = range; x->q = q;
    x->out = intout((t_lprand *)x); }
    return x; }
    Can anyone see what might be causing this? I'm still (slowly) learning my way around the API. Originally I was attempting to just create the rndarray with malloc in the lopass function but after looking through the documentation and examples thought the sysmem_xxx stuff was a better way to ensure compatibility. Perhaps I have implemented it incorrectly?
    Thanks for any thoughts.

    • May 03 2016 | 11:54 am
      x->rndarray = (long *)sysmem_newptrclear(q *sizeof(long));
    • May 03 2016 | 12:00 pm
      Hey, thanks for the reply. I'll give that a go. I thought I might be missing something around that declaration. Thanks again.