Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can a private member be changed without calling a non-const method?
    primarykey
    data
    text
    <p>I have a problem. I spend around 5 hours trying everything, but I was not even able to reproduce it properly so I include the simplified original source code. I apologize for the extent, but I wanted to include all the relevant information I found out so far. This is one of the few times I feel completely powerless and kindly request your help. Any ideas are welcome. Also any comments that can bring at least some light to the matter. The behaviour in this case is a complete mystery to me.</p> <p>I am programming in QtCreator in Ubuntu. I am trying to develop a framework to solve mathematical problems using a Population of candidate solutions, which should evolve into the true solution.</p> <p>There are 3 classes involved: Population, PopulationMember and Problem:</p> <pre><code>class PopulationMember { QVector&lt;Number&gt; x_; QVector&lt;Number&gt; y_; Population* population_; EDIT: Sorry, this is a pointer void evaluate(); friend class Population; }; class Population {p public: QList&lt;PopulationMember*&gt; members_; // created on the heap Problem* problem_; // created on the heap const Problem* readProblem() const;p void evaluate(); void report() const; ... }; class Problem { public: void evaluate(PopulationMember&amp;)const; }; </code></pre> <p>Usually my program runs in loops, where the population calls its various methods. One of them is Population::evaluate(). My program ran great until I introduced some new methods of Population. </p> <pre><code>for (int i = 1; i != 101; ++i) { Population-&gt;evaluate(); Population-&gt;someMethod1(); Population temp = Population-&gt;clone(); temp-&gt;someMethod2(); Population-&gt;append(temp); Population-&gt;someNewMethod(); Population-&gt;someSorting(); if (i % 10 == 0) Population-&gt;report(); } </code></pre> <p>Then I get a segmentation error in the middle of program. The strangest thing is that it happens only after the 10 loops, after the population executed report(). Also after some experimentation, when I excluded all the operations which require dynamic allocation of some sort (strings) from the report() method, I do not get the error. Conversely when I disable the sorting method (uses either std::sort or qSort) the problem stops. Also when I leave the actions done by the temp Population, there is no problem. So I started to debug the program. I let it complete 10 loops and started to debug step by step. I went into Population->evaluate();</p> <pre><code>void Population::evaluate() { for (Iterator it = begin(); it != end(); ++it) { std::cout &lt;&lt; problem_; // debug see bellow: (*it) -&gt; evaluate(); // If I change to problem_-&gt;evaluate(**it); the program works. } </code></pre> <p>}</p> <p>debug: The addres printed out is 0xbffff628. This is same as the previous 10 * population_->members_.count() printouts.</p> <p>I go inside the (*it) -> evaluate(); Here I switch to assembly code:</p> <pre><code> 864 (*it) -&gt; evaluate(); 0x805380c &lt;+122&gt;: lea -0x10(%ebp),%eax 0x805380f &lt;+125&gt;: mov %eax,(%esp) 0x8053812 &lt;+128&gt;: call 0x8055d84 &lt;QList&lt;PopulationMember*&gt;::iterator::operator*() const&gt; 0x8053817 &lt;+133&gt;: mov (%eax),%eax 0x8053819 &lt;+135&gt;: mov %eax,(%esp) 0x805381c &lt;+138&gt;: call 0x805ae08 &lt;PopulationMember::evaluate()&gt; </code></pre> <p>I go inside the call of function at the last instruction. At the instant I do this, all the attributes in problem_ become not accessible according to my debugger. At this point all is lost.</p> <pre><code>void PopulationMember::evaluate() { population_ -&gt; readProblem() -&gt; evaluate(*this); } 135 { 0x805ae08 &lt;+000&gt;: push %ebp 0x805ae09 &lt;+001&gt;: mov %esp,%ebp 0x805ae0b &lt;+003&gt;: sub $0x18,%esp 136 population_ -&gt; readProblem() -&gt; evaluate(*this); 0x805ae0e &lt;+006&gt;: mov 0x8(%ebp),%eax 0x805ae11 &lt;+009&gt;: mov 0x4(%eax),%eax 0x805ae14 &lt;+012&gt;: mov %eax,(%esp) 0x805ae17 &lt;+015&gt;: call 0x8051bc4 &lt;Population::readProblem() const&gt; 0x805ae1c &lt;+020&gt;: mov 0x8(%ebp),%edx 0x805ae1f &lt;+023&gt;: mov %edx,0x4(%esp) 0x805ae23 &lt;+027&gt;: mov %eax,(%esp) 0x805ae26 &lt;+030&gt;: call 0x804e962 &lt;Problem::evaluate(PopulationMember&amp;) const&gt; 137 } 0x805ae2b &lt;+035&gt;: leave 0x805ae2c &lt;+036&gt;: ret 0x805ae2d nop const Problem* Population::readProblem() const { std::cout &lt;&lt; problem_ &lt;&lt; std::endl; // debug see bellow: return problem_; } </code></pre> <p>debug: Finally the address the problem_ is pointing at becomes 0xbffff780 instead of 0xbffff628. An increment of 344</p> <p>This happens always. The increment is 344. If I make some minor changes in the program, the address changes, but the difference between these two addresses remains 344. This is all the more puzzling, since the size of all my three classes is less than 100. </p> <p>The program crashes inside the void Problem::evaluate(PopulationMember&amp;)const; method as soon as some logic is involved.</p> <p>EDIT:</p> <pre><code>Population Population::clone() { Population temp(*this); return temp; } Population::Population(const Population&amp; population) { this-&gt;setProblem(population.problem_); Population::ConstIterator cit; for (cit = population.constBegin(); cit != population.constEnd(); ++cit) this-&gt;addCopy(*cit); this-&gt;ownsMembers_ = true; } void Population::addCopy (PopulationMember* populationMember) { PopulationMember *temp = new PopulationMember(*populationMember); // Memberwise temp -&gt; population_ = this; members_.push_back(populationMember); } Population::~Population() { if (ownsMembers_) foreach (PopulationMember* X, members_) delete X; } void Population::append(Population&amp; population) { if (population.ownsMembers_) { members_.append(population.members_); population.ownsMembers_ = false; } else members_.append(population.members_); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload