getvalueof freebytes ?

Dec 4, 2010 at 5:00pm

getvalueof freebytes ?

Hello maxers,

i try to implement a [pattrstorage] compatible external, and i have a question about memory management :

t_max_err myobj_getvalueof(t_myobj *x, long *ac, t_atom **av)
    {
        if (ac && av) {
            if (*ac && *av) {
                // memory has been passed in; use it.
            } else {
                // allocate enough memory for your data
                *av = (t_atom *)getbytes(sizeof(t_atom));
            }
            *ac = 1; // our data is a single floating point value
            atom_setfloat(*av, x->objvalue);
        }
        return MAX_ERR_NONE;
    }

Is there any reason that : “memory has been passed in” ;
Should not be *always* NULL and 0 ?

#53723
Dec 4, 2010 at 9:33pm

As I understand, if the object which calls your attribute getter method has already allocated some memory for the return value then you should use that allocated memory. This could be the scenario if the object that is querying your data is expecting to get, for instance, always a single t_atom (or, let’s say in a more generic way, an arbitrary but pre-fixed number of t_atoms) in which case it is more efficient for the object to store that t_atom in its object struct instead of allocating memory for that atom each single time it wants to make a query to your attribute’s getter method.

Hope this helps,
Ádám

#193251
Dec 5, 2010 at 7:01am

Hello Siska,

yep, could be a scenario ; but if size of expecting data is not equal to data to get ; what my object is supposed to do ? Of course it may never happened ; but in case ;-)

1. return MAX_ERR_GENERIC ?
2. free the memory (query) and allocate new one ; not very safe …
3. do nothing.

I prefer the 1. ; any opinion ?

#193252
Dec 5, 2010 at 12:39pm

Hi,

I’m not sure about the ‘standard’ way which legacy objects do in these scenarios. However, option 2 is definitely wrong since you’re freeing memory you didn’t allocate. If the t_atom that was passed in is a static member of a struct or is a local variable of a function then you would probably corrupt the memory and you’d crash the program sooner or later.
To be honest, I guess that most of the objects will call your getter in the 0-NULL way. I guess that the scenario when these data is not empty is reserved for some really specific background stuff or for cases when the caller object knows exactly the kind (and amount of) data it might get. Imagine this: I write an external that has an internal array of atoms and has a custom attribute representing the size of this internal array. I also write another external that at some point needs to query the size of that array. In this specific case I know exactly that I’ll get a single atom, therefore I won’t make the getter method allocate each time a new portion of memory (that’s quite inefficient memory management), instead, I’ll have a local variable of type t_atom an I’ll always call the getter method with the address of that local variable.
What I would do in your case is first of all, a test: if the size of the expected data is equals to the size of the data you want to return, I’d just use it. If not, I would return MAX_ERR_GENERIC however, I’d also return something at least half-useful info (I don’t know your situation, but at this point you might need to be creative — or you could set each incoming t_atom to 0 or some other empty value, like setting the type of the atom to A_NOTHING). Don’t forget that most of the developers usually won’t check for the error value returned…

Hope this helps,
Ádám

P.S.: Siska is my family name, BTW.

#193253
Dec 5, 2010 at 4:44pm

Hello Ádám,

I think i’ll just return MAX_ERR_GENERIC in case of allocated memory, as this external will never be used by other people than me ; i just try to learn C in a crashproof way ;-)

Thanks for reply.

Nicolas.

#193254
Dec 6, 2010 at 1:54pm

Here’s the quick and simple response:

You should use the allocated memory if it is passed in (never writing more values than the argc passed in). This can be done in certain instances for efficiency reasons.

Allocate memory if it is not passed in.

Never reallocate memory which has been passed in.

#193255

You must be logged in to reply to this topic.