How to prevent the creation of an object when bad arguments are typed ?

Apr 1, 2013 at 10:07am

How to prevent the creation of an object when bad arguments are typed ?

I’d like to be sure the object is not created at all if either argument’s value or type is not correct.

I would like the object to appear the same way as when an object is not found.

Thank you in advance.

#67449
Apr 1, 2013 at 11:03am

Hi,

Just return NULL in your “toto_new” method ?

void *flop_new(t_symbol *s, long argc, t_atom *argv)
{
//
t_flop *x = NULL;

if ((x = (t_flop *)object_alloc(flop_class))) {

if (Error) {
    object_free(x);
    x = NULL;
}

}
return x;
//
}

In this code i call object_free(x) to avoid memory leaks ; that will call your “toto_free” method. Be sure there to check if objects have been properly initialized before to free them.

HTH

#242656
Apr 1, 2013 at 4:41pm

Oh I see. Merci !

#242657
Apr 11, 2013 at 2:14am

Using only x = NULL was not enough. I tried to use the return 0 instruction instead of return x to prevent object creation when required. However it seems that it was necessary only in one case but I can’t figure out why…

void *rb_randomize_new(t_symbol *s, long argc, t_atom *argv)
 {
	 //t_rb_randomize *x ; // local variable (pointer to a t_rb_randomize data structure)
	 t_rb_randomize *x = NULL ;
	 if (x = (t_rb_randomize *)object_alloc(rb_randomize_class)) {

		srand (time(NULL)) ; // seed rand with time

		x->proxy = proxy_new(x, 1, &x->proxy_inletnum);	// fully-flexible inlet for any type (remember one default inlet is always provided)
        x->outlet = outlet_new(x, NULL);				// fully-flexible outlet for any type

		// initialize L and R inlet atoms to (int) 0
		atom_setlong(&x->l, 0);
		atom_setlong(&x->range, 0);

		long i;

		// object instantiation, NEW STYLE

		if (argc > 2) { // more than two arguments
			object_warn((t_object *)x, "only two first arguments will be used", argc);
			x = NULL;
		} else if (argc == 2) { // two arguments
			for (i = 0; i < 2; i++) {
				if (i == 0) { // first argument sets range
					switch ((argv + i)->a_type) {
						case A_LONG:
							atom_setlong(&x->range, atom_getlong(argv+i));
							break;
						case A_FLOAT:
							atom_setfloat(&x->range, atom_getfloat(argv+i));
						default:
							object_error((t_object *)x, "forbidden argument type (int or float only)");
							x = NULL;
							return 0;
							//rb_randomize_free(x);
							break;
					}

				}
				else { // second argument makes second inlet triggerable
					if ((argv + i)->a_type == A_LONG) {
						if (atom_getlong(argv+i) == 0 || atom_getlong(argv+i) == 1) {
							x->rangetriggers = atom_getlong(argv+i) ;
							return x;
						}
						else {
							x->rangetriggers = 0;
							object_error((t_object *)x, "second argument's value should be either 1 or 0");
							x = NULL;
							//return 0;
							//rb_randomize_free(x);
						}
					}
					else {
						x->rangetriggers = 0;
						object_error((t_object *)x, "forbidden argument type (int only)");
						x = NULL;
						//return 0;
						//rb_randomize_free(x);
					}

				}
			}
		}
		else { // only one argument
			switch (argv->a_type) {
				case A_LONG:
					atom_setlong(&x->range, atom_getlong(argv));
					return x;
					break;
				case A_FLOAT:
					atom_setfloat(&x->range, atom_getfloat(argv));
					//return x;
					break;
				default:
					object_error((t_object *)x, "forbidden argument type");
					x = NULL;
					//return 0;
					//rb_randomize_free(x);
					break;
			}

		}
	}
	//post(" new rb.randomize object instance added to patch...",0); // post important info to the max window when new instance is created
	return x;
 }
#242658
Apr 11, 2013 at 6:08am

Hi,

I don’t know if it is that, but in your code it seems you do not manage the (argc == 0) case safely.

IMHO (and that’s a matter of taste) :

- Don’t use redondant comments that pollute more that helps.
- Never write twice the same code ; write a function instead ; be lazy ;
- And don’t mix error management with normal code ; hard to understand and debug also.

Forum coding so may have typos and/or errors :

#define RB_GOOD     0
#define RB_ERR_1    1
#define RB_ERR_2    2

void *rb_randomize_new(t_symbol *s, long argc, t_atom *argv)
{
    t_rb_randomize *x = NULL;

    if (x = (t_rb_randomize *)object_alloc(rb_randomize_class)) {
    //
    long i, err = RB_GOOD;

    srand(time(NULL)); 

    x->proxy = proxy_new(x, 1, &x->proxy_inletnum);
    x->outlet = outlet_new(x, NULL);

    atom_setlong(&x->l, 0);
    atom_setlong(&x->range, 0);

    if (argc > 2) {
        err = RB_ERR_1;
    } else {
        for (i = 0; i < argc; i++) {
            if (i == 0) {
                err = randomize_setRange(x, argv + i);
            } else {
                err = randomize_setTriggerable(x, argv + i);
            }
        }
    }

    if (err) {
    //
    switch (err) {
    case RB_ERR_1 :
        object_warn((t_object *)x, "only two first arguments will be used", argc);
        break;
    case RB_ERR_2 :
        object_error((t_object *)x, "forbidden argument type (int or float only)");
        break;
    case RB_ERR_3 :
        object_error((t_object *)x, "second argument's value should be either 1 or 0");
        break;
    }

    object_free(x);
    x = NULL;
    //
    }
    //
    }

    return x;
}

long randomize_setRange(t_rb_randomize *x, t_atom *a)
{
    long err = RB_GOOD;

    switch (atom_getype(a)) {
        case A_LONG     : atom_setlong(&x->range, atom_getlong(a)); break;
        case A_FLOAT    : atom_setfloat(&x->range, atom_getfloat(a)); break;
        default         : err = RB_ERR_1; break;
    }

    return err;
}

My 2 cents.

#242659
Apr 11, 2013 at 9:58am

For your purposes using:

x = NULL;
return x;

or simply:

return 0;

makes absolutely no difference.
Both constructs will prevent the creation of the object.

- Luigi

#242660
Apr 11, 2013 at 2:21pm

Thanks Nicolas, thanks Luigi.

Is the object_free mandatory here ?

#242661
Apr 11, 2013 at 2:36pm

Hi,

By calling “object_free” in the code you trigger the call of your “toto_free” method ; in the case you don’t allocate anything in the heap (or if you have already freed it) in your object it is not necessary to do it.

#242662
Apr 11, 2013 at 2:49pm

if you called object_alloc, you should call object_free:

if (x = object_alloc(whatever)) {

    // decide that arguments
    if (args == nogood) {
        object_free(x);
        x = NULL;
    }
}

return x;
#242663
Apr 11, 2013 at 3:12pm
#242664
Apr 13, 2013 at 10:33am

This is a great example Nicolas. Thanks!

#242665

You must be logged in to reply to this topic.