[Gambas-devel] Store GB_VARIANT in memory

Tobias Boege tobias at ...692...
Mon Aug 13 22:40:39 CEST 2012


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





More information about the Devel mailing list