[Gambas-devel] New(er) enumeration API

Benoît Minisini gambas at ...1...
Mon Oct 8 15:52:57 CEST 2012


Le 03/10/2012 22:22, Tobias Boege a écrit :
> On Wed, 03 Oct 2012, Tobias Boege wrote:
>> On Wed, 03 Oct 2012, Tobias Boege wrote:
>>> On Wed, 03 Oct 2012, Beno?t Minisini wrote:
>>>> Le 03/10/2012 20:56, Tobias Boege a ?crit :
>>>>> On Wed, 03 Oct 2012, Tobias Boege wrote:
>>>>>> Hi,
>>>>>>
>>>>>> today while debugging the new List code for gb.data I encountered problems
>>>>>> with the new enumeration API. There are _few_ places to learn from (I took
>>>>>> CResult.c) but apparently something doesn't quite work out with it:
>>>>>>
>>>>>> I want to run through all references I manage for a chunk in a List (a
>>>>>> 'chunk' contains some Variants). These are the 'Current' pointer and all the
>>>>>> enumerations currently active. The ultimate goal is to update members of
>>>>>> these reference structures just because the elements they point to in the
>>>>>> chunk changed their location. The convenience macro looks like this:
>>>>>>
>>>>>> #define for_all_persistent_vals(list, vp, es, ebuf)                     \
>>>>>> 	for (ebuf = GB.BeginEnum(list), vp = &list->current, es = NULL;	\
>>>>>> 	vp ? 1 : (GB.EndEnum(ebuf), 0);					\
>>>>>> 		!GB.NextEnum() ? (es = (struct enum_state*) GB.GetEnum(),\
>>>>>> 			vp = &es->next) : (vp = NULL))
>>>>>>
>>>>>> (admittely not a very appealing piece of code)
>>>>>>
>>>>>> where 'list' is the Gambas List object, 'vp' is a pointer to the structure
>>>>>> I want to update, 'es' is my struct enum_state and 'ebuf' is whatever I get
>>>>>> back from GB.BeginEnum() and have to pass to GB.EndEnum().
>>>>>>
>>>>>> The thing now is that, even if no enumeration runs in the Gambas code, I get
>>>>>> some 'es' which contains information that could actually have been valid (in
>>>>>> fact, it refers to the last enumerated object in the last enumeration).
>>>>>> For some reason, the important part (the pointer to the chunk which sits at
>>>>>> offset 0 from the 'es' pointer) is set to NULL and thus, my library
>>>>>> segfaults on NULL pointer dereference.
>>>>>>
>>>>>
>>>>> Actually, I set it myself to NULL which indicates the end of enumeration to
>>>>> the List_next routine. But why does that 'es' appear again without being in
>>>>> enumeration?
>>>>>
>>>>> I have a really bad feeling now since I only get the 'es' filled if I put in
>>>>> some basically unrelated Gambas code before the List.Take() from which the
>>>>> above problem originates...
>>>>>
>>>>> I just want to know: Is it possible under normal circumstances to get an old
>>>>> non-running enumerator from that GB.*Enum() interface?
>>>>>
>>>>>> Benoit, can you please enlighten me if I am doing something wrong with these
>>>>>> functions?
>>>>>
>>>>
>>>> I can't know. See me the full code because you can't do what you want
>>>> between GB.BeginEnum() ... GB.EndEnum() (i.e. you can't do something
>>>> that may call another enumeration-related function).
>>>>
>>>> Moreover, I'm not sure that your spaghetti macro is right. Can you
>>>> rewrite it as clear as possible (i.e. without using the ',' operator)?
>
> Arrg! And the loop body must be before that unrolled while-body, so that:
>
> ebuf = GB.BeginEnum(list);
> vp   = &list->current; /* Begin with Current */
> es   = NULL; /* Just signal that vp is not an enumerator */
> while (vp) {
> 	/* Here goes the loop body, modifying vp */
>
> 	/* Get all enumerators next */
> 	if (!GB.NextEnum())
> 		break; /* In the macro done via vp = NULL */
> 	es = GB.GetEnum();
> 	vp = &es->next;
> }
> GB.EndEnum(ebuf);
>

Can you commit your code and give me a project example of the bug?

-- 
Benoît Minisini




More information about the Devel mailing list