我有一個問題。我花了大約5個小時嘗試一切,但我甚至無法正確再現它,所以我包括了簡化的原始源代碼。我對此表示歉意,但我想包括迄今爲止發現的所有相關信息。這是我感覺完全沒有力量的少數時間之一,並請求你的幫助。任何想法都歡迎。此外,任何意見都可以爲此事帶來至少一些啓示。這種情況下的行爲對我來說是完全神祕的。如何在不調用非const方法的情況下更改私有成員?
我在Ubuntu的QtCreator編程。我正在嘗試開發一個框架來解決使用候選解決方案的人口數學問題,這應該演變成真正的解決方案。
有3類涉及:人口,PopulationMember和問題:
class PopulationMember
{
QVector<Number> x_;
QVector<Number> y_;
Population* population_; EDIT: Sorry, this is a pointer
void evaluate();
friend class Population;
};
class Population
{p
public:
QList<PopulationMember*> 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&)const;
};
通常我的程序循環,那裏的人口調用它的各種方法運行。其中之一是Population :: evaluate()。我的程序運行良好,直到我介紹了一些新的人口方法。
for (int i = 1; i != 101; ++i)
{
Population->evaluate();
Population->someMethod1();
Population temp = Population->clone();
temp->someMethod2();
Population->append(temp);
Population->someNewMethod();
Population->someSorting();
if (i % 10 == 0)
Population->report();
}
然後我在程序中間出現分割錯誤。最奇怪的是,只有在執行report()後的10個循環後纔會發生。另外經過一些實驗,當我排除了所有需要從report()方法動態分配某些類型(字符串)的操作時,我不會收到錯誤。相反,當我禁用排序方法(使用std :: sort或qSort)時,問題就會停止。當我離開臨時人口完成的行動時,也沒有問題。所以我開始調試該程序。我讓它完成10個循環並開始逐步調試。我進入Population-> evaluate();
void Population::evaluate()
{
for (Iterator it = begin(); it != end(); ++it)
{
std::cout << problem_; // debug see bellow:
(*it) -> evaluate(); // If I change to problem_->evaluate(**it); the program works.
}
}
調試: 打印出來的ADDRES是0xbffff628。這與以前的10 * population_-> members_.count()打印輸出相同。
我走進(* it) - > evaluate();在這裏,我切換到彙編代碼:
864 (*it) -> evaluate();
0x805380c <+122>: lea -0x10(%ebp),%eax
0x805380f <+125>: mov %eax,(%esp)
0x8053812 <+128>: call 0x8055d84 <QList<PopulationMember*>::iterator::operator*() const>
0x8053817 <+133>: mov (%eax),%eax
0x8053819 <+135>: mov %eax,(%esp)
0x805381c <+138>: call 0x805ae08 <PopulationMember::evaluate()>
我在最後一條指令的函數調用中進入。在執行此操作的瞬間,根據我的調試器,problem_中的所有屬性都無法訪問。 在這一點上都失去了。
void PopulationMember::evaluate()
{
population_ -> readProblem() -> evaluate(*this);
}
135 {
0x805ae08 <+000>: push %ebp
0x805ae09 <+001>: mov %esp,%ebp
0x805ae0b <+003>: sub $0x18,%esp
136 population_ -> readProblem() -> evaluate(*this);
0x805ae0e <+006>: mov 0x8(%ebp),%eax
0x805ae11 <+009>: mov 0x4(%eax),%eax
0x805ae14 <+012>: mov %eax,(%esp)
0x805ae17 <+015>: call 0x8051bc4 <Population::readProblem() const>
0x805ae1c <+020>: mov 0x8(%ebp),%edx
0x805ae1f <+023>: mov %edx,0x4(%esp)
0x805ae23 <+027>: mov %eax,(%esp)
0x805ae26 <+030>: call 0x804e962 <Problem::evaluate(PopulationMember&) const>
137 }
0x805ae2b <+035>: leave
0x805ae2c <+036>: ret
0x805ae2d nop
const Problem* Population::readProblem() const
{
std::cout << problem_ << std::endl; // debug see bellow:
return problem_;
}
調試: 最後problem_所指向的地址變成0xbffff780而不是0xbffff628。增量爲344
總是會發生這種情況。增量是344.如果我在程序中做了一些小的改動,地址就會改變,但這兩個地址之間的差異仍然是344.這更令人費解,因爲我所有三個類的大小都小於100.
該程序在void內部崩潰Problem:evaluate(PopulationMember &)const;方法儘快涉及一些邏輯。
編輯:
Population Population::clone()
{
Population temp(*this);
return temp;
}
Population::Population(const Population& population)
{
this->setProblem(population.problem_);
Population::ConstIterator cit;
for (cit = population.constBegin(); cit != population.constEnd(); ++cit)
this->addCopy(*cit);
this->ownsMembers_ = true;
}
void Population::addCopy (PopulationMember* populationMember)
{
PopulationMember *temp = new PopulationMember(*populationMember); // Memberwise
temp -> population_ = this;
members_.push_back(populationMember);
}
Population::~Population()
{
if (ownsMembers_)
foreach (PopulationMember* X, members_)
delete X;
}
void Population::append(Population& population)
{
if (population.ownsMembers_)
{
members_.append(population.members_);
population.ownsMembers_ = false;
}
else
members_.append(population.members_);
}
是否有可以簡化問題的任何方式?你能告訴我們克隆()方法嗎? –
你試過valgrind嗎? –
人口人口:: clone()const { Population temp(* this); return temp; } –