[Gambas-devel] Store GB_VARIANT in memory

Benoît Minisini gambas at ...1...
Tue Aug 14 15:47:38 CEST 2012


Le 13/08/2012 22:40, Tobias Boege a écrit :
> On Mon, 13 Aug 2012, Beno?t Minisini wrote:
>> Le 11/08/2012 19:13, Tobias Boege a ?crit :
>>> Hi,
>>>
>>> I want to save a GB_VARIANT into a buffer, Ref() the object inside, if any,
>>> and return in later properly. My code looks something like this:
>>>
>>> static void *val;
>>>
>>> BEGIN_METHOD(Store, GB_VARIANT value)
>>>
>>> 	/* Tried also GB_VARIANT here, but the error differs only, maybe
>>> 	 * because of the application... */
>>> 	GB.Alloc(&val, sizeof(GB_VARIANT_VALUE));
>>> 	GB.StoreVariant(ARG(value), val);
>>>
>>> END_METHOD
>>>
>>> BEGIN_METHOD_VOID(Restore)
>>>
>>> 	GB.ReturnVariant(val);
>>> 	GB.Free(&val);
>>>
>>> END_METHOD
>>>
>>> Suppose each Store() matches a Restore(), I get Segfaults in VALUE_write()
>>> and since I don't quite look through Gambas datatype and storage (yesterday
>>> crusaded against object reference counting successfully, though) I thought
>>> it's simpler to ask directly - the array types were not really helpful to
>>> me as I could not get to the exact point where memory allocation takes
>>> place. Or, if I were there (ARRAY_add_data()?), I didn't get it.
>>>
>>> BTW, the above is clearly simplified, I need allocating val dynamically.
>>>
>>> Regards,
>>> Tobi
>>>
>>
>> Oops, I forgot you... :-)
>>
>> A Gambas Variant is store inside a GB_VARIANT_VALUE structure. You don't
>> need to allocate it on the heap.
>>
>
> Did you read the last paragraph in my previous mail? I need that
> dynamically on the heap, but see below.
>
>> // A Variant must be initialized to NULL
>>
>> static GB_VARIANT_VALUE val = { T_NULL };
>>
>> BEGIN_METHOD(Store, GB_VARIANT value)
>>
>>     GB.StoreVariant(ARG(value), &val);
>>
>> END_METHOD
>>
>> BEGIN_METHOD_VOID(Restore)
>>
>>     // The variant is copied in a temporary place.
>>     GB.ReturnVariant(&val);
>>
>>     // Free the stored variant.
>>     // But you can't do it now, because the Variant will
>>     // be referenced after the function has returned only.
>>     // GB.StoreVariant(NULL, &val);
>>
>> END_METHOD
>>
>> As you can't release the Variant inside the Restore method, you must
>> free the contents of 'val' in the '_exit' special method of your class.
>>
>> Regards,
>>
>> --
>> Beno?t Minisini
>
> Sorry, I don't understand what to do now. Maybe I have to be clearer to not
> talk past each other. I started a gb.adt for abstract datatypes as I
> remember some people needed that and to get better in programming Gambas
> components at all - gb.ncurses still waits and will probably be more
> complex than what I am used to with the Gambas API. I already got circular
> double-linked lists (almost without memory problems) working and implemented
> Stack and Queue on top of a general Deque class (using linked lists. It is
> questionable if these are really needed as we have Variant[] already but to
> this later, please).
> One memory bug torments me for two days now and I want to be really sure it
> is not located in the Deque class but in the Lists.
>
> The above problem concerns, as you might expect now, the Deque functions.
> The object will receive multiple Variants which can be Objects or
> non-Objects like Integer. How would I store and link them into the Deque
> list and later unlink and restore so that reference-counted types get their
> ref and the others do not? I think, for this aim, the GB.StoreVariant() is
> the right function.
> But when an element is dequeued from a Queue, the memory occupied by the
> list node and the GB_VARIANT_VALUE buffer should be freed.
> Something like the code above already worked but valgrind reported two
> problems in VALUE_write() ("Conditional jump or move depends on
> uninitialised value(s)"). I am convinced that my test application is causing
> these by pushing two Integers onto the Stack (due to location and number of
> valgrind warnings)... Any remarks on this?
> Here is the actual code, however:
>
> BEGIN_METHOD(Deque_PushFront, GB_VARIANT value)
>
> 	void *newval;
>
> 	GB.Alloc(&newval, sizeof(GB_VARIANT_VALUE));
> 	GB.StoreVariant(ARG(value), newval);
> 	CDEQUE_push_front(THIS, newval); // Just links the copy to the list
>
> END_METHOD
>
> BEGIN_METHOD_VOID(Deque_PopFront)
>
> 	void *value;
>
> 	if (CDEQUE_is_empty(THIS)) {
> 		GB.ReturnNull();
> 		return;
> 	}
> 	value = CDEQUE_pop_front(THIS); // Retrieves newval from above and
> 					// deletes the list node
> 	GB.ReturnVariant(value);
> 	GB.Free(&value);
>
> END_METHOD
>
> (Don't mind the names ;-))
>
> Re-thinking the whole situation: Do I even need to copy the Variant I
> receive?
> If the Deque gets to hold an Integer, for example, it is expected that it
> holds a copy of it so that the original Integer can be modified without
> changing the queued value. So concluding, it is _indeed_ necessary to
> copy, right?
>
> Thank you for consideration.
>
> Regards,
> Tobi
>

Too much english for me in one sole mail. :-)

Did you look at how the Collection class has been implemented?

	--> /main/gbx/gbx_c_collection.c

Or simpler the Variant[] array?

	--> /main/gbx/gbx_c_array.c

They both store and retrieve variants. Or you can look at how the 
Control.Tag property in gb.qt4, it's a variant stored inside a 
dynamically allocated object.

	--> /gb.qt4/src/CWidget.cpp

If the Variant is not global, but stored inside a dynamically allocated 
C structure, nothing changes:

--8<-------------------------------------------------------

// My object

typedef
   struct {
     GB_BASE ob;
     GB_VARIANT_VALUE tag;
     }
   MYOBJECT;

#define THIS ((MYOBJECT *)_object)

BEGIN_METHOD(Store, GB_VARIANT value)

   GB.StoreVariant(ARG(value), &THIS->tag);

END_METHOD

BEGIN_METHOD_VOID(Restore)

   // The variant is copied in a temporary place.
   GB.ReturnVariant(&THIS->tag);

   // Free the stored variant.
   // But you can't do it now, because the Variant will
   // be referenced after the function has returned only.
   // GB.StoreVariant(NULL, &THIS->tag);

END_METHOD

--8<-------------------------------------------------------

Regards,

-- 
Benoît Minisini




More information about the Devel mailing list