MSP Object instantiation crash

Peter McCulloch's icon

I'm working on an MSP object. I copied the project from a known-good Xcode project and I've compared it with the examples, but I keep getting obex errors when I try to load it into Max which, from what I've read, usually indicate that there's something amiss in the setup. The problem is that I'm getting this with a very straightforward setup.

I went through the Xcode project and swapped over everything that had the name of the old project in it, and I've cleaned, etc. Can anyone provide some insight?

Here's the relevant code:
#include "ext.h"
#include "ext_obex.h"
#include "z_dsp.h"

static t_class *foo_class;

typedef struct _foo {

    t_pxobject m_obj;
    // rest of the structure’s fields
} t_foo;

// Prototypes
t_int *foo_perform(t_int *w);
void foo_dsp(t_foo *x, t_signal **sp, short *count);
void *foo_new(void);
void foo_mode(t_foo *x, int mode);
void foo_assist(t_foo *x, void *b, long m, long a, char *s);
void foo_float(t_foo *x, double f);

int main(void)
{    

    // NEW METHOD
    t_class *c;

    c = class_new("foo~", (method)foo_new, (method)dsp_free, sizeof(t_foo), NULL, 0);

    class_dspinit(c);    // new style object version of dsp_initclass();    

    class_addmethod(c, (method)foo_dsp,"dsp", A_CANT, 0);
    class_addmethod(c, (method)foo_mode, "mode", A_LONG, 0);
    class_addmethod(c, (method)foo_float,        "float",    A_FLOAT, 0);
    class_addmethod(c, (method)foo_assist,    "assist",    A_CANT, 0);

    class_register(CLASS_BOX, c);    // register class as a box class
    foo_class = c;
    return 0;
}

void *foo_new(void) {
    t_foo *c = (t_foo *) object_alloc(foo_class);

    dsp_setup((t_pxobject *)c,3); // Three inlets: input, freq, res
    // Always crashes here...

// Create outlet
    outlet_new((t_object *)c, "signal");    // Create outlet

    //c->freq = 60.f;
    //c->res = 0.5;

    return (c);

}

t_int *foo_perform(t_int *w) {
return (w+6)
}

void foo_dsp(t_foo *x, t_signal **sp, short *count) {

    x->smprate = sp[0]->s_sr;
    x->vecSize = sp[0]->s_n;
    x->invsmp = 1./x->vecSize; //
    x->invSR = 1.f/sp[0]->s_sr;

    dsp_add(foo_perform, 5, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,x);
}

Here's the crash log:
0 com.cycling74.MaxMSP     0x000b7e0c class_obexoffset_get + 6
1 com.cycling74.MaxMSP     0x000b8b8f object_obex_get + 29
2 com.cycling74.MaxMSP     0x000b8beb object_obex_lookup + 39
3 com.cycling74.MaxAPI     0x00ebb9d2 object_obex_lookup + 45
4 com.cycling74.MaxAudioAPI     0x0e591677 z_dsp_setup + 68
5 com.apple.PM_foo_     0x0f7fbcd2 foo_new + 50

$Adam's icon

Hi Peter,

did you try replacing the line

outlet_new((t_object *)c, "signal");    // Create outlet

to

outlet_new((t_pxobject *)c, "signal");    // Create outlet

in your foo_new() method? I'm not sure that helps, just wondering, maybe...

Cheers,
Ádám

Peter McCulloch's icon

I did, but to no avail. Thanks, anyways!

$Adam's icon

OK, now that I think on it, that was a quite silly idea. I created a new project and compiled your submitted code, and I can report that the code itself compiles and runs fine.

According to the crash log, it crashes on dsp_setup when it tries to guess the location of the obex member of your struct with class_obexoffset_get (which AFAIK calls the ANSI C offsetof macro). Since this seems to be (at least for me) some sort of aligning issue with the t_foo struct, it gives the impression that t_foo actually contains more fields than those you have posted. Could you please verify this?

Also, did you try copying an SDK-example (after verifying that that particular example compiles fine, of course) and just replacing its code with your one?

It seems an interesting bug, though.

Best,
Ádám

Peter McCulloch's icon

I spent some time debugging it today. You are correct, I have quite a few more fields in the struct. I have two tables in the struct:
float tab[4096];
float ftom_tab[4096];

and the code compiles when I remove the second one. (!?) I went through it methodically, disabled variables one at a time, and that definitely makes the difference between crash and no crash.

I'm new to C (coming from Java), so I suspect I'm making the kind of mistakes that Java won't allow you to make. It's probably time to go brush up on pointers...

leighhunt's icon

If it clarifies, I seem to remember having a similar issue some time ago, and indeed the struct size has a upper limit of something like 32KB.
Someone with wizzo knowledge of SDK dev may correct me if I am wrong.
Regards,
Leigh

Emmanuel Jourdan's icon

That's correct. Allocating in the yourobject_new() method, freeing in the yourobject_free() method as mentioned by vanille béchamel is the way to go.

Peter McCulloch's icon

Good to know, and many thanks for everyone who helped me! I'll try it this afternoon.

Peter McCulloch's icon

Thanks everyone for the contributions. This did the trick. As a brief follow-up to vanille béchamel's post: (and for anyone who's searching this later...)

void myobject_free (t_myobject *x)
{
    dsp_free((t_pxobject *)x); // Call this first to prevent max from crashing when freeing while DSP is on
sysmem_freeptr (x->freq);

}