[Xapian-devel] setting ValueRangeProcessor at runtime

Olly Betts olly at survex.com
Mon Nov 16 01:50:20 GMT 2009


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



More information about the Xapian-devel mailing list