Peter Karman | 15 Nov 04:32
Favicon

setting ValueRangeProcessor at runtime

I want to set a variable number and type of ValueRangeProcessors at run time
based on a configuration file. But I seem to be running into (what I think is) a
C++ scope issue.

I tried just a simple test to see if I could add 5 VPs in a loop.

    Xapian::QueryParser qparser;
    Xapian::Query query;

    int vp = 0;
    while(vp < 5) {
        Xapian::StringValueRangeProcessor sproc(vp++);
        qparser.add_valuerangeprocessor(&sproc);
    }

    query = qparser.parse_query(myquery);

That will compile, but when that code executes I get this error:

pure virtual method called
terminate called without an active exception
Abort trap

I *think* what's happening is that the sproc object goes out of scope at the end
of the while() loop and is GC'd by the time the qparser tries to actually parse
the query, so the qparser is trying to access a pointer that has been freed.
But that's just a guess based on my limited knowledge of C++.

What's the correct way to dynamically add a series of ValueRangeProcessors?

--

-- 
Peter Karman  .  http://peknet.com/  .  peter <at> peknet.com
Olly Betts | 16 Nov 02:50
Favicon
Gravatar

Re: setting ValueRangeProcessor at runtime

On Sat, Nov 14, 2009 at 09:32:20PM -0600, Peter Karman wrote:
> I want to set a variable number and type of ValueRangeProcessors at run time
> based on a configuration file. But I seem to be running into (what I think
> is) a C++ scope issue.
> 
> I tried just a simple test to see if I could add 5 VPs in a loop.
> 
>     Xapian::QueryParser qparser;
>     Xapian::Query query;
> 
>     int vp = 0;
>     while(vp < 5) {
>         Xapian::StringValueRangeProcessor sproc(vp++);
>         qparser.add_valuerangeprocessor(&sproc);
>     }
> 
>     query = qparser.parse_query(myquery);
> 
> 
> That will compile, but when that code executes I get this error:
> 
> pure virtual method called
> terminate called without an active exception
> Abort trap
> 
> I *think* what's happening is that the sproc object goes out of scope at the
> end of the while() loop and is GC'd by the time the qparser tries to actually
> parse the query, so the qparser is trying to access a pointer that has been
> freed.  But that's just a guess based on my limited knowledge of C++.

C++ doesn't use GC.  The object sproc is precisely deleted at the end of the
block.

This isn't just an issue with C++.  The Python bindings carefully keep
references for you, so this isn't an issue there.  The Perl bindings
deliberately leak a reference, which isn't great, but avoids this issue
at least.  The other bindings require you to keep the objects in scope.

There's a ticket about this issue:

http://trac.xapian.org/ticket/186

> What's the correct way to dynamically add a series of ValueRangeProcessors?

In C++ you dynamically allocate with new:

    Xapian::StringValueRangeProcessor * sproc;
    sproc = new Xapian::StringValueRangeProcessor(vp++);
    qparser.add_valuerangeprocessor(sproc);

To avoid leaking them (which isn't really a problem if this is a short lived
process like a CGI script, but would be for a query server), stick them into
a vector or similar and delete them later:

    Xapian::QueryParser qparser;
    Xapian::Query query;
    vector<Xapian::ValueRangeProcessor*> vrps;

    int vp = 0;
    while(vp < 5) {
	Xapian::StringValueRangeProcessor * sproc;
	sproc = new Xapian::StringValueRangeProcessor(vp++);
	qparser.add_valuerangeprocessor(sproc);
	vrps.push_back(sproc);
    }

    query = qparser.parse_query(myquery);

    // Once you're done with qparser:
    vector<Xapian::ValueRangeProcessor*>::const_iterator i;
    for (i = vrps.begin(); i != vrps.end(); ++i) {
	delete *i;
    }

Cheers,
    Olly
Peter Karman | 16 Nov 04:53
Favicon

Re: setting ValueRangeProcessor at runtime


Olly Betts wrote on 11/15/09 7:50 PM: > On Sat, Nov 14, 2009 at 09:32:20PM -0600, Peter Karman wrote: >> What's the correct way to dynamically add a series of ValueRangeProcessors? > > In C++ you dynamically allocate with new: > > Xapian::StringValueRangeProcessor * sproc; > sproc = new Xapian::StringValueRangeProcessor(vp++); > qparser.add_valuerangeprocessor(sproc); > > To avoid leaking them (which isn't really a problem if this is a short lived > process like a CGI script, but would be for a query server), stick them into > a vector or similar and delete them later
brilliant. thanks for the very clear examples and explanation, Olly. -- -- Peter Karman . http://peknet.com/ . peter <at> peknet.com

Gmane