在这个简单的代码中找不到我的内存泄漏
Can't find my memory leak in this simple code
我 100% 肯定我涵盖了在内存丢失之前从堆中删除内存的所有内容,但 valgrind 似乎不同意。非常感谢任何帮助查找以下代码中的泄漏的帮助!我似乎无法弄清楚是什么原因造成的
Card * S = new Card[subsetSize];
Card * M = nullptr;
int subsetPrice = 0, subsetProfit = 0;
for(int i = 0; i < subsetSize; i++){
S[i] = problemCards[cardIndexesToAdd[i]];
subsetPrice += S[i].getPrice();
subsetProfit += S[i].getProfit();
}
// Evaluate the subset's cost and profit
if(subsetPrice <= maxToSpend){
if(subsetProfit > maxProfit){
maxProfit = subsetProfit;
if(M != nullptr)
delete[] M;
M = S;
S = nullptr;
mSize = subsetSize;
}
}
else{
if(S != nullptr){
delete[] S;
S = nullptr;
}
}
// output code for M
if(M != nullptr)
delete[] M;
当 (subsetPrice <= maxToSpend) == true
但 (subsetProfit > maxProfit) == false
.
时你泄漏了 S
让我们一步步看看你在做什么:
为S分配内存。将M指向null。
Card * S = new Card[subsetSize];
Card * M = nullptr;
如果满足条件A(subsetPrice <= maxToSpend),并且满足条件B(subsetProfit > maxProfit),交换M指向分配给S的内存,并设置S指向null .
if (subsetPrice <= maxToSpend){
if (subsetProfit > maxProfit){
maxProfit = subsetProfit;
if (M != nullptr)
delete[] M;
M = S;
S = nullptr;
mSize = subsetSize;
}
}
如果不满足条件 A,则释放 S 指向的内存。
else{
if(S != nullptr){
delete[] S;
S = nullptr;
}
}
取消分配 M 指向的内存。
if(M != nullptr)
delete[] M;
因此,如果满足条件 A,但不满足条件 B,则 S 既不会被释放,也不会转移给 M!内存泄漏。
抱歉,这是一条评论,但我是新来的,还不能这样做。
new 不需要检查 nullptr 是否内存不足。 Thx@jerry-coffin
你所有的 delete [] 都在 if () 或嵌套的 if () 语句中。如果这个泄漏,你错过了添加一个带有删除 [] 的 else 并且你错过了 else 语句。
这似乎是一个片段,但事实上,我认为没有理由使用 M 或其分配给 S。您可能应该考虑在最后进行一次删除。
与其扮演侦探并追踪这个特定的内存泄漏,我建议学习编写代码,这样一开始就不会引起此类问题。最明显的第一点是 使用 std::vector
而不是尝试自己处理所有内存管理。可能没有其他单一步骤可以像习惯这样做那样快速消除问题。
当你使用它的时候,整个class几乎所有的问题都不复存在了,因为你有一个拥有内存的对象,而当那个对象超出范围,它会完全自动释放它拥有的内存。即使抛出 when/if 异常,您的代码甚至 尝试 都不会处理,它也能正常工作。
std::vector<Card> subset(subsetSize);
for (int i=0; i<subsetSize; i++) {
subset.push_back(problemCards[cardIndexesToAdd[i]]);
subsetPrice += subset.back().getPrice();
subsetProfit += subset.back().getProfit();
}
if (subsetProfit > maxProfit && subsetPrice < maxPrice) {
maxSubset = std::move(subset);
maxProfit = subsetProfit;
}
// code to print out maxSubset goes here
如果您想更进一步,可以使用(例如)Boost indirect_iterator 代替 cardIndexesToAdd
。这将使您可以将标准算法直接应用于您关心的子集。有了这个,您可以很容易地完全避免复制当前子集——您只需使用 indirect_iterator 就地迭代原始集合。
您还可以为 Card
定义一个 operator+
,它将对价格和利润字段求和:
Card operator+(Card const &left, Card const &right) {
return Card(left.price+right.price, left.profit+right.profit);
}
有了这个,以及前面提到的 indirect_iterator,将子集的利润加起来可能是这样的:
Card subset_stats = std::accumulate(subset.begin(), subset.end(), Card());
同样,我们可以为 Card
定义一个比较运算符,它根据利润 and/or 成本生成结果:
// Assuming we care primarily about maximizing profit, secondarily about
// price, so if one subset produces more profit, it's better. If they produce
// the same profit, the lower cost wins.
bool operator<(Card const &a, Card const &b) {
if (a.profit == b.profit)
return a.price < b.price;
return b.profit < a.profit;
}
有了它,我们可以直接比较 Card
s,例如:if (a < b) ..
并得到有意义的结果。
我 100% 肯定我涵盖了在内存丢失之前从堆中删除内存的所有内容,但 valgrind 似乎不同意。非常感谢任何帮助查找以下代码中的泄漏的帮助!我似乎无法弄清楚是什么原因造成的
Card * S = new Card[subsetSize];
Card * M = nullptr;
int subsetPrice = 0, subsetProfit = 0;
for(int i = 0; i < subsetSize; i++){
S[i] = problemCards[cardIndexesToAdd[i]];
subsetPrice += S[i].getPrice();
subsetProfit += S[i].getProfit();
}
// Evaluate the subset's cost and profit
if(subsetPrice <= maxToSpend){
if(subsetProfit > maxProfit){
maxProfit = subsetProfit;
if(M != nullptr)
delete[] M;
M = S;
S = nullptr;
mSize = subsetSize;
}
}
else{
if(S != nullptr){
delete[] S;
S = nullptr;
}
}
// output code for M
if(M != nullptr)
delete[] M;
当 (subsetPrice <= maxToSpend) == true
但 (subsetProfit > maxProfit) == false
.
S
让我们一步步看看你在做什么:
为S分配内存。将M指向null。
Card * S = new Card[subsetSize]; Card * M = nullptr;
如果满足条件A(subsetPrice <= maxToSpend),并且满足条件B(subsetProfit > maxProfit),交换M指向分配给S的内存,并设置S指向null .
if (subsetPrice <= maxToSpend){ if (subsetProfit > maxProfit){ maxProfit = subsetProfit; if (M != nullptr) delete[] M; M = S; S = nullptr; mSize = subsetSize; } }
如果不满足条件 A,则释放 S 指向的内存。
else{ if(S != nullptr){ delete[] S; S = nullptr; } }
取消分配 M 指向的内存。
if(M != nullptr) delete[] M;
因此,如果满足条件 A,但不满足条件 B,则 S 既不会被释放,也不会转移给 M!内存泄漏。
抱歉,这是一条评论,但我是新来的,还不能这样做。
new 不需要检查 nullptr 是否内存不足。 Thx@jerry-coffin
你所有的 delete [] 都在 if () 或嵌套的 if () 语句中。如果这个泄漏,你错过了添加一个带有删除 [] 的 else 并且你错过了 else 语句。
这似乎是一个片段,但事实上,我认为没有理由使用 M 或其分配给 S。您可能应该考虑在最后进行一次删除。
与其扮演侦探并追踪这个特定的内存泄漏,我建议学习编写代码,这样一开始就不会引起此类问题。最明显的第一点是 使用 std::vector
而不是尝试自己处理所有内存管理。可能没有其他单一步骤可以像习惯这样做那样快速消除问题。
当你使用它的时候,整个class几乎所有的问题都不复存在了,因为你有一个拥有内存的对象,而当那个对象超出范围,它会完全自动释放它拥有的内存。即使抛出 when/if 异常,您的代码甚至 尝试 都不会处理,它也能正常工作。
std::vector<Card> subset(subsetSize);
for (int i=0; i<subsetSize; i++) {
subset.push_back(problemCards[cardIndexesToAdd[i]]);
subsetPrice += subset.back().getPrice();
subsetProfit += subset.back().getProfit();
}
if (subsetProfit > maxProfit && subsetPrice < maxPrice) {
maxSubset = std::move(subset);
maxProfit = subsetProfit;
}
// code to print out maxSubset goes here
如果您想更进一步,可以使用(例如)Boost indirect_iterator 代替 cardIndexesToAdd
。这将使您可以将标准算法直接应用于您关心的子集。有了这个,您可以很容易地完全避免复制当前子集——您只需使用 indirect_iterator 就地迭代原始集合。
您还可以为 Card
定义一个 operator+
,它将对价格和利润字段求和:
Card operator+(Card const &left, Card const &right) {
return Card(left.price+right.price, left.profit+right.profit);
}
有了这个,以及前面提到的 indirect_iterator,将子集的利润加起来可能是这样的:
Card subset_stats = std::accumulate(subset.begin(), subset.end(), Card());
同样,我们可以为 Card
定义一个比较运算符,它根据利润 and/or 成本生成结果:
// Assuming we care primarily about maximizing profit, secondarily about
// price, so if one subset produces more profit, it's better. If they produce
// the same profit, the lower cost wins.
bool operator<(Card const &a, Card const &b) {
if (a.profit == b.profit)
return a.price < b.price;
return b.profit < a.profit;
}
有了它,我们可以直接比较 Card
s,例如:if (a < b) ..
并得到有意义的结果。