Enormous Increase In the Use Of Memory - c++

I've got a code where I need to create a map with key values as double (value of the f-test between two clusters. I need to calculate the residual sum of squares for this) and the mapped value of cluspair which is pair of the class Cluster that I created. Map aims to store the F-test values between the all clusters so that I would not need to do the calculation again and again in every step. BTW cluster is a tree structure where every cluster contains two subclusters and the stored values are 70-dimensional vectors.
Problem is, in order to calculate the RSS, I need to implement a recursive code where I need to find the distance of every element of the cluster with the mean of the cluster and this seems to be consuming an enormous amount of memory. When I create the same map with the key values being the simple distance between the means of two clusters, the program uses minimal memory so I think the increase in the memory use is caused by the call of the recursive function RSS. What should I do to manage the memory use in the code below? In its current implementation the system runs out of memory and windows closes the application saying that the system ran out of virtual memory.
The main code:
map<double,cluspair> createRSSMap( list<Cluster*> cluslist )
{
list<Cluster*>::iterator it1;
list<Cluster*>::iterator it2;
map<double,cluspair> rtrnmap;
for(it1=cluslist.begin(); it1!= --cluslist.end() ;it1++)
{
it2=it1;
++it2;
cout << ".";
list<Cluster*>::iterator itc;
double cFvalue=10000000000000000000;
double rIt1 = (*it1)->rss();
for(int kk=0 ; it2!=cluslist.end(); it2++)
{
Cluster tclustr ((*it1) , (*it2));
double r1 = tclustr.rss();
double r2= rIt1 + (*it2)->rss();
int df2 = tclustr.getNumOfVecs() - 2;
double fvalue = (r1 - r2) / (r2 / df2);
if(fvalue<cFvalue)
{
cFvalue=fvalue;
itc=it2;
}
}
cluspair clp;
clp.c1 = *it1;
clp.c2 = *itc;
bool doesexists = (rtrnmap.find(cFvalue) != rtrnmap.end());
while(rtrnmap)
{
cFvalue+= 0.000000001;
rtrnmap= (rtrnmap.find(cFvalue) != rtrnmap.end());
}
rtrnmap[cFvalue] = clp;
}
return rtrnmap;
}
and the imlementation of the function RSS:
double Cluster::rss()
{
return rss(cnode->mean);
}
double Cluster::rss(vector<double> &cmean)
{
if(cnode->numOfVecs==1)
{
return vectorDist(cmean,cnode->mean);
}
else
{
return ( ec1->rss(cmean) + ec2->rss(cmean) );
}
}
Much thanks in advance. I really don't know what to do at this point.
below is the code with that I use to create a map with keys being simple euclidian distance between two cluster means. As I've said above, it is quite similar and uses minimal memory. It only differs in the calculation of the fvalue. Instead of the recursive calculation, there is the calculation of simple distance of means of two clusters. Hope it helps to identify the problem
map<double,cluspair> createDistMap( list<Cluster*> cluslist )
{
list<Cluster*>::iterator it1;
list<Cluster*>::iterator it2;
map<double,cluspair> rtrnmap;
for(it1=cluslist.begin(); it1!= --cluslist.end() ;it1++)
{
it2=it1;
++it2;
cout << ".";
list<Cluster*>::iterator itc;
double cDist=1000000000000000;
for(int kk=0 ; it2!=cluslist.end(); it2++)
{
double nDist = vectorDist( (*it1)->getMean(),(*it2)->getMean());
if (nDist<cDist)
{
cDist = nDist;
itc=it2;
}
}
cluspair clp;
clp.c1 = *it1;
clp.c2 = *itc;
bool doesexists = (rtrnmap.find(cDist) != rtrnmap.end());
while(doesexists)
{
cDist+= 0.000000001;
doesexists = (rtrnmap.find(cDist) != rtrnmap.end());
}
rtrnmap[cDist] = clp;
}
return rtrnmap;
}
implementation of vectorDist()
double vectorDist(vector<double> vec1, vector<double> vec2)
{
double sqrsum=0;
double tempd=0;
int vs = vec1.size();
for ( int i=0;i<vs;i++)
{
tempd = vec1[i] - vec2[i];
sqrsum += tempd*tempd;
}
return sqrsum;
}
Edit:
BTW I've tried this alternative implementation which still fails to control the memory usage
double Cluster::rss()
{
list<double> fvals;
rss(cnode->mean , fvals);
double sum=0;
list<double>::iterator tpit;
for(tpit=fvals.begin() ; tpit != fvals.end() ; ++tpit)
{
sum += *tpit;
}
return sum;
}
void Cluster::rss(vector<double> &cmean , list<double> &fvals)
{
if(cnode->numOfVecs==1)
{
fvals.push_back( vectorDist(cmean,cnode->mean) );
}
else
{
ec1->rss(cmean , fvals);
ec2->rss(cmean , fvals);
}
}

If you're running out of memory you have a very deep tree or your Cluster objects are large or both. Try creating another tree data structure of doubles with the same topology as your Cluster tree and call it RSS tree to hold the RSS values. Calculate the bottom nodes' rss values and then recursively fill out the rest of the values in the RSS tree. This way you aren't holding the cluster objects in memory while you do the rss calculation.

Related

How can I optimize Astar for vast empty spaces?

I am creating a game with a 3D grid for flying entities, So I have a lot of points and connections in the air where there aren't any obstructions. I didn't want to decrease the resolution of my grid so I thought I could just skip over chunks (or empties as I call them) of the Astar map while they're not containing any obstructions, and I modified Godot's Astar algorithm to do this.
Unfortunately this ended up being slower than looping through points one at a time due to the way I implemented this modification, which needs to loop through all the edge points of an empty.
2D representation of how one edge point of an empty connects to all other edge points:
This ends up looping through a larger number of points than letting the A* algorithm work it's way through the empty.
So I'm sorta stumped on how to make this more efficient while still preserving the most optimal path.
I could potentially narrow down what faces of the empty should be scanned over by first comparing the center points of all 8 faces of the empty (as my grid consists of hexagonal prisms). Or maybe I should somehow use the face center points of the empty's faces exclusively instead of all edge points.
I mainly want to know if anyone has worked on an issue like this before, and if so what would be the recommended solution?
Here is the astar loop for reference:
bool AStar::_solve(Point *begin_point, Point *end_point, int relevant_layers) {
pass++;
//make sure parallel layers are supported
// or if *relevant_layers is 0 then use all points
bool supported = relevant_layers == 0 || (relevant_layers & end_point->parallel_support_layers) > 0;
if (!end_point->enabled || !supported) {
return false;
}
bool found_route = false;
Vector<Point *> open_list;
SortArray<Point *, SortPoints> sorter;
begin_point->g_score = 0;
begin_point->f_score = _estimate_cost(begin_point->id, end_point->id);
open_list.push_back(begin_point);
while (!open_list.empty()) {
Point *p = open_list[0]; // The currently processed point
if (p == end_point) {
found_route = true;
break;
}
sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list
open_list.remove(open_list.size() - 1);
p->closed_pass = pass; // Mark the point as closed
//if the point is part of an empty, look through all of the edge points of said empty (as to skip over any points within the empty).
OAHashMap<int, Point*> connections;
PoolVector<Empty*> enabled_empties;
int size = p->empties.size();
PoolVector<Empty*>::Read r = p->empties.read();
for (int i = 0; i < size; i++) {
Empty* e = r[i];
supported = relevant_layers == 0 || (relevant_layers & e->parallel_support_layers) > 0;
//if the empty is enabled and the end point is not within the empty
if (e->enabled && supported && !end_point->empties.has(e)) {
enabled_empties.append(e);
//can travel to any edge point
for (OAHashMap<int, Point*>::Iterator it = e->edge_points.iter(); it.valid; it = e->edge_points.next_iter(it)) {
int id = *it.key;
Point* ep = *(it.value);
ep->is_neighbour = false;
//don't connect to the same point
if (id != p->id && (i == 0 || !connections.has(id))) {
connections.set(id, ep);
}
}
}
}
//add neighbours to connections
for (OAHashMap<int, Point*>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
int id = *it.key;
Point* np = *(it.value);// The neighbour point
np->is_neighbour = true;
//don't need to check for duplicate point connections if no empties
if (size == 0 || !connections.has(id)) {
//don't add points within enabled empties since they're meant to be skipped over
if (np->empties.size() > 0 && !np->on_empty_edge) {
bool in_enabled_empty = false;
PoolVector<Empty*>::Read r1 = np->empties.read();
for (int i = 0; i < np->empties.size(); i++) {
if (enabled_empties.has(r1[i])) {
in_enabled_empty = true;
break;
}
}
if (!in_enabled_empty) {
connections.set(id, np);
}
}
else {
connections.set(id, np);
}
}
}
for (OAHashMap<int, Point *>::Iterator it = connections.iter(); it.valid; it = connections.next_iter(it)) {
Point *e = *(it.value); // The neighbour point
//make sure parallel layers are supported
// or if *relevant_layers is 0 then use all points
supported = relevant_layers == 0 || (relevant_layers & e->parallel_support_layers) > 0;
if (!e->enabled || e->closed_pass == pass || !supported) {
continue;
}
real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * e->weight_scale;
bool new_point = false;
if (e->open_pass != pass) { // The point wasn't inside the open list.
e->open_pass = pass;
open_list.push_back(e);
new_point = true;
} else if (tentative_g_score >= e->g_score) { // The new path is worse than the previous.
continue;
}
e->prev_point = p;
e->prev_point_connected = e->is_neighbour;
e->g_score = tentative_g_score;
e->f_score = e->g_score + _estimate_cost(e->id, end_point->id);
if (new_point) { // The position of the new points is already known.
sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw());
} else {
sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw());
}
}
}
return found_route;
}
Note: I'm still not exactly sure what the sorter does.
the entire code can be seen here in a_star.cpp and a_star.h
Edit:
if anyone wants to reference or use this, I've modified the Astar code to add user-defined octants and to use a user-defined straight line function (they are user-defined so they can work with any type of grid) to be used between octants when possible to further decrease runtime, and it works very well in terms of speed. Though the pathing is not optimal, especially when adding a lot of obstacles/restricting the available positions.

Unable to delete a list element in C++

I am working on a small game and came across a big problem with lists.
Here's my code:
void cCollisionManager::checkCollision(cPlayer * pPlayer, std::list<cAsteroid*> *asteroidList, std::list<cShot*> *ShotList)
{
sf::FloatRect PlayerBox = pPlayer->getSprite()->getGlobalBounds();
for (auto it : *asteroidList) {
for (auto es : *ShotList) {
sf::FloatRect asteroidboundingBox = it->getSprite()->getGlobalBounds();
sf::FloatRect ShotBox = es->getSprite().getGlobalBounds();
if (asteroidboundingBox.intersects(ShotBox)) {
it = asteroidList->erase(it);
*pPlayer->pPunkte += 1;
std::cout << *pPlayer->pPunkte << std::endl;
}
if (asteroidboundingBox.intersects(PlayerBox)) {
if (*pPlayer->phealth >= 0.f)
*pPlayer->phealth -= 0.5f;
}
}
}
}
I used SFML and basically everything works. But if I want to delete the colliding asteroid and the shot, the programs exits with an error. In the if loop I tried to erase the object, but the compiler also gives an error saying that the argument type is not the same as the object type I am giving to it.
EDIT
I had another look at the other question, you recommended to me, but still I haven't found out how to solve that problem. So if I changed my code to a while loop, the game couldn't handle it, because the Collision Manager is actually called in every single Call of the SFML main loop. So it would just get stuck in my collision loop. So I changed my code a bit, but still, things are not working.
Don't modify sequences that are being enumerated with range-for. Use
iterators and the appropriate result of an erase. – WhozCraig
This is actually the answer to it. I did the mistake - using a for loop and not a while loop and so I had some big issues and bad construction ideas for my code - luckily everything now works!
Here is my final code:
auto it = asteroidList->begin();
auto es = ShotList->begin();
while (it != asteroidList->end()) {
sf::FloatRect PlayerBox = pPlayer->getSprite()->getGlobalBounds();
sf::FloatRect asteroidboundingBox = (*it)->getSprite()->getGlobalBounds();
while (es != ShotList->end())
{
sf::FloatRect ShotBox = (*es)->getSprite().getGlobalBounds();
if (asteroidboundingBox.intersects(ShotBox)) {
it = asteroidList->erase(it);
es = ShotList->erase(es);
std::cout << "Asteroid destroyed" << std::endl;
*pPlayer->pPunkte += 1;
std::cout << *pPlayer->pPunkte << std::endl;
}
if (es != ShotList->end())
es++;
}
if (asteroidboundingBox.intersects(PlayerBox))
{
if (*pPlayer->phealth > 3.f) {
*pPlayer->phealth -= 5.f;
it = asteroidList->erase(it);
}
else
*pPlayer->pBStateAlive = false;
}
if (it != asteroidList->end()) {
it++;
es = ShotList->begin();
}
}
}

c++ find and handle each lines is slower than php

Hello i created a program to handle a config file line by checking each lines and get the config blocks but for first time i made it with php and the speed was amazing. we have some blocks like this
Block {
}
php program can read each line and detect about 50,000 of this blocks in just 1 second after that i went to c++ to create my program in c++ but i saw a very very bad problem. my program was too slow (read 50,000 of this blocks in 55 seconds) while my php codes was exactly the same of c++ codes (in action and activity). php was 55x faster than c++ while the codes are the same.
this is my code in php
const PATH = "conf.txt";
if(!file_exists(PATH)) die("path_not_found");
if(!is_readable((PATH))) die("path_not_readable");
$Lines = explode("\r\n", file_get_contents(PATH));
class Block
{
public $Name;
public $Keys = array();
public $Blocks = array();
}
function Handle(& $Lines, $Start, & $Return_block, & $End_on)
{
for ($i = $Start; $i < count($Lines); $i++)
{
while (trim($Lines[$i]) != "")
{
$Pos1 = strpos($Lines[$i], "{");
$Pos2 = strpos($Lines[$i], "}");
if($Pos1 !== false && ($Pos2 === false || $Pos2 > $Pos1)) // Detect { in less position
{
$thisBlock = new Block();
$thisBlock->Name = trim(substr($Lines[$i], 0, $Pos1));
$Lines[$i] = substr($Lines[$i], $Pos1 + 1);
Handle($Lines, $i, $thisBlock, $i);
$Return_block->Blocks[] = $thisBlock;
}
else { // Detect } in less position than {
$Lines[$i] = substr($Lines[$i], $Pos2 + 1);
$End_on = $i;
return;
}
}
}
}
$DefaultBlock = new Block();
Handle($Lines, 0, $DefaultBlock, $NullValue);
$OutsideKeys = $DefaultBlock->Keys;
$Blocks = $DefaultBlock->Blocks;
echo "Found (".count($OutsideKeys).") keys and (".count($Blocks).") blocks.<br><br>";
and this is my code in C++
string Trim(string & s)
{
auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c) {return std::isspace(c); });
auto wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c) {return std::isspace(c); }).base();
return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback));
}
class Block
{
private:
string Name;
vector <Block> Blocks;
public:
void Add(Block & thisBlock) { Blocks.push_back(thisBlock); }
Block(string Getname = string()) { Name = Getname; }
int Count() { return Blocks.size(); }
};
void Handle(vector <string> & Lines, size_t Start, Block & Return, size_t & LastPoint, bool CheckEnd = true)
{
for (size_t i = Start; i < Lines.size(); i++)
{
while (Trim(Lines[i]) != "")
{
size_t Pos1 = Lines[i].find("{");
size_t Pos2 = Lines[i].find("}");
if (Pos1 != string::npos && (Pos2 == string::npos || Pos1 < Pos2)) // Found {
{
string Name = Trim(Lines[i].substr(0, Pos1));
Block newBlock = Block(Name);
Lines[i] = Lines[i].substr(Pos1 + 1);
Handle(Lines, i, newBlock, i);
Return.Add(newBlock);
}
else { // Found }
Lines[i] = Lines[i].substr(Pos2 + 1);
return;
}
}
}
}
int main()
{
string Cont;
___PATH::GetFileContent("D:\\conf.txt", Cont);
vector <string> Lines = ___String::StringSplit(Cont, "\r\n");
Block Return;
size_t Temp;
// The problem (low handle speed) start from here not from including or split
Handle(Lines, 0, Return, Temp);
cout << "Is(" << Return.Count() << ")" << endl;
return 0;
}
as you can see, this codes are exactly the same in action but i don't know why php handling in this code is 55x faster than my c++ codes. you can create a txt file and create about 50,000 of this block's
Block {
}
and test it yourself. please help me to fix this. i am really confused (same codes but not same performance
php = 50,000 blocks and detect in 1 second
c++ = 50,000 blocks and detect in 55 seconds (and maybe more) !
i have no problem in my program design. because i got my performance completely on php but my problem is on c++ that is 55x slower than php in same code action !
i am using (visual studio 2017) to compile this program (c++)
First, "code" is singular, not plural.
C++ is a very different language than php. It is not "the same code", and it is nowhere near the same in action.
For example, these two lines:
Block newBlock = Block(Name);
Return.Add(newBlock);
First create a Block on the stack, and then call Block's copy constructor to make another one inside the vector. You then throw away the stack object.
Also, vectors guarantee that they are contiguous, so as you add new Blocks via your Add method, vector will occasionally stop, allocate another chunk of memory (twice as big as the last one, iirc), copy everything over to that new chunk, and then free the old one. Either preallocate the vector (via vector::reserve()), or consider using something like a deque that doesn't guarantee continuity in memory if you don't need that property.
I also don't know what ___String::StringSplit does, but you are almost certain to have the same vector growth problem in reading your file.
Culprit is in these 2 lines:
Handle(Lines, i, newBlock, i);
Return.Add(newBlock);
Let's say you have 5 levels of 1 block each. What Happens on bottom one? You copy one instance of block. What happens on level 4? You copy 2 blocks (parent and its child). So for level 5 you make 15 copies - 1+2+3+4+5. Look at this diagram:
Handle level1 copies 5 blocks (`Return`->level4->level3->level4->level5)
Handle level2 copies 4 blocks (`Return`->level3->level4->level5)
Handle level3 copies 3 blocks (`Return`->level4->level5
Handle level4 copies 2 blocks (`Return`->level5)
Handle level5 copies 1 block (`Return`)
Formula is:
S = ( N + N^2 ) / 2
so for levels 20 you would do 210 copies and so on.
Suggestion is to use move semantics to avoid this copy:
// change method Add to this
void Add(Block thisBlock) { Blocks.push_back(std::move(thisBlock)); }
// and change this call
Return.Add( std::move( newBlock ) );
Or allocate blocks dynamically using smart pointers
Out of simple curiousity, try this Trim implementation instead:
void _Trim(std::string& result, const std::string& s) {
const auto* ptr = s.data();
const auto* left = ptr;
const auto* end = s.data() + s.size();
while (ptr < end && std::isspace(*ptr)) {
++ptr;
}
if (ptr == end) {
result = "";
return;
}
left = ptr;
while (end > left && std::isspace(*(end-1))) {
--end;
}
result = std::string(left, end);
}
std::string Trim(const std::string& s) {
// Not sure if RVO would fire for direct implementation of _Trim here
std::string result;
_Trim(result, s);
return result;
}
And another optimization:
void Add(Block& thisBlock) {
Blocks.push_back(std::move(thisBlock));
}
// Don't use thisBlock after call to this function. It is
// far from being pretty but it should avoid *lots* of copies.
I wonder if you'll get better result. Pls let me know.

Plot only part of QwtCurve in real time plot

I have a QVector in which I'm constantly appending data so I can plot on a QwtPlot. But with a high frequency I guess the vector becames too large and the program crashes.
My question is, how can I create a QwtCurve which is only beggining in some point of time, bacause the time that has already passed is not necessary in the vector as it was already plotted.
here's my code:
QVector<double> xv;
QVector<double> cv1;
QVector<double> cv2;
as global variables,
void gui::process_new_info(QByteArray array)
{
int v = 0;
double f = ui->frequency->value();
xv.append(sizeof_array/f);
char *buf = array.data();
if (ui->ecgPlux->isChecked() == true || ui->channel_1->currentIndex() != 0)
{
cv1.append(buf[1]);
QwtPlotCurve *curve1 = new QwtPlotCurve;
curve1->attach(plot_all[0]);
curve1->setData(xv,cv1);
curve1->setPen(QPen(Qt::blue,1));
plot_all[0]->replot();
QwtPlotCurve *curve2 = new QwtPlotCurve;
curve2->attach(plot[0]);
curve2->setData(xv,cv1);
curve2->setPen(QPen(Qt::blue,1));
plot[0]->replot();
}
if (ui->xyzPlux->isChecked() == true || ui->channel_2->currentIndex() != 0)
{
cv2.append(buf[2]);
QwtPlotCurve *curve3 = new QwtPlotCurve;
curve3->attach(plot_all[1]);
curve3->setData(xv,cv2);
curve3->setPen(QPen(Qt::blue,1));
plot_all[0]->replot();
QwtPlotCurve *curve4 = new QwtPlotCurve;
curve4->attach(plot[1]);
curve4->setData(xv,cv1);
curve4->setPen(QPen(Qt::blue,1));
plot[1]->replot();
}
//printf ("%d ->", buf[0]);
fprintf (data, "%d,", buf[0]);
for (int i = 1; i < 9; i++)
{
v = buf[i];
//printf ("%d,", v);
fprintf (data, "%d,", v);
}
//printf ("\n");
fprintf (data, "\n");
sizeof_array++;
}
QwtPlotCurve
http://qwt.sourceforge.net/class_qwt_plot_curve.html
inherits from QwtPlotSeriesItem
http://qwt.sourceforge.net/class_qwt_plot_series_item.html
There is a warning in setData
The item takes ownership of the data object, deleting it when its not used anymore.
It probably isn't the fact that you are growing too big... it may be that you are accessing something that Qwt deleted.
Run it in a debugger, and look at the stack trace for where it died, or put in a bunch of qDebug() lines to see where it is dying.
If it is something with the data being too large, you could pop off items off of the head of your vector, before setting the vector.
Hope that helps.

BulkLoading the R* tree with spatialindex library

After successfully building the R* tree with spatial library inserting records one-by-one 2.5 million of times, I was trying to create the R* tree with bulkloading. I implemented the DBStream class to iteratively give the data to the BulkLoader. Essentially, it invokes the following method and prepared a Data (d variable in the code) object for the Bulkloader:
void DBStream::retrieveTuple() {
if (query.next()) {
hasNextBool = true;
int gid = query.value(0).toInt();
// allocate memory for bounding box
// this streets[gid].first returns bbox[4]
double* bbox = streets[gid].first;
// filling the bounding box values
bbox[0] = query.value(1).toDouble();
bbox[1] = query.value(2).toDouble();
bbox[2] = query.value(3).toDouble();
bbox[3] = query.value(4).toDouble();
rowId++;
r = new SpatialIndex::Region();
d = new SpatialIndex::RTree::Data((size_t) 0, (byte*) 0, *r, gid);
r->m_dimension = 2;
d->m_pData = 0;
d->m_dataLength = 0;
r->m_pLow = bbox;
r->m_pHigh = bbox + 2;
d->m_id = gid;
} else {
d = 0;
hasNextBool = false;
cout << "stream is finished d:" << d << endl;
}
}
I initialize the DBStream object and invoke the bulk loading in the following way:
// creating a main memory RTree
memStorage = StorageManager::createNewMemoryStorageManager();
size_t capacity = 1000;
bool bWriteThrough = false;
fileInMem = StorageManager
::createNewRandomEvictionsBuffer(*memStorage, capacity, bWriteThrough);
double fillFactor = 0.7;
size_t indexCapacity = 100;
size_t leafCapacity = 100;
size_t dimension = 2;
RTree::RTreeVariant rv = RTree::RV_RSTAR;
DBStream dstream();
tree = RTree::createAndBulkLoadNewRTree(SpatialIndex::RTree::BLM_STR, dstream,
*fileInMem,
fillFactor, indexCapacity,
leafCapacity, dimension, rv, indexIdentifier);
cout << "BulkLoading done" << endl;
Bulk loading calls my next() and hasNext() functions, retrieved my data, sorts it and then seg faults in the building phase. Any clues way? Yeah, the error is:
RTree::BulkLoader: Building level 0
terminate called after throwing an instance of 'Tools::IllegalArgumentException'
The problem supposedly lies in the memory allocation and a few bugs in the code (somewhat related to memory allocation too). Firstly one needs to properly assign the properties of the Data variable:
memcpy(data->m_region.m_pLow, bbox, 2 * sizeof(double));
memcpy(data->m_region.m_pHigh, bbox + 2, 2 * sizeof(double));
data->m_id = gid;
Second (and most importantly) getNext must return a new object with all the values:
RTree::Data *p = new RTree::Data(returnData->m_dataLength, returnData->m_pData,
returnData->m_region, returnData->m_id);
return returnData;
de-allocation of memory is done by RTree so no care is needed to be taken here.