I never invoke free
in my code, so I don't know why I'm getting this error.
I wrote a program to find integer partitions of a number. It worked fine. Then I decided I wanted to try and use a pointer to the vector to avoid unnecessarily copying my std::vector<ints>
's between iterations of a loop. It compiles (using g -std=c 11 -o main main.cpp). When I execute the program, I get this error message:
main(5629,0x115dcfe00) malloc: *** error for object 0x7ffed1c05a30: pointer being freed was not allocated
main(5629,0x115dcfe00) malloc: *** set a breakpoint in malloc_error_break to debug
Why am I getting this error? Thank you in advance.
Here's my code:
#include <stdexcept>
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using std::cout; using std::endl;
using std::vector;
typedef vector<int> ints;
void print_ints(vector<int>);
void print_ints_vec(vector<vector<int>>);
void int_part(int, vector<vector<int>>&);
int main()
{
vector<vector<int>> partition;
int_part(5, partition);
print_ints_vec(partition);
return 0;
}
void int_part(int sum, vector<vector<int>>& res)
{
vector<int> init_xs = vector<int>{sum};
vector<int>* xs = &init_xs; // POINTER INITIALIZED TO vector<int>
int current_sum = sum;
while (true)
{
current_sum = accumulate(xs->begin(), xs->end(), 0); //
if (current_sum == sum)
{
res.push_back(*xs); //
vector<int> next_xs;
vector<int>::iterator it = find(xs->begin(), xs->end(), 1); //
if (it == xs->begin()) return; //
copy(xs->begin(), it, back_inserter(next_xs)); //
next_xs[next_xs.size() - 1] -= 1; //
xs = &next_xs; // POINTER REASSIGNED TO ANOTHER vector<int>
}
else
{
int tail = xs->back(); //
int diff = sum - current_sum;
int m = std::min(tail, sum - tail);
int next_tail = current_sum m > sum ? diff : m;
xs->push_back(next_tail); //
}
}
}
void print_ints(ints v) // PRINT UTILITY
{
cout << "[ ";
for (const int& n : v) { cout << n << "; "; }
cout << "]" << endl;
}
void print_ints_vec(vector<ints> v) // PRINT UTILITY
{
cout << "[ \n";
for (const vector<int>& xs : v) { cout << " "; print_ints(xs); }
cout << "]" << endl;
}
CodePudding user response:
xs = &next_xs;
is bad because next_xs
is a local variable whose lifetime ends at end of the scope. After the end of scope, dereferencing xs
is illegal until a pointer to a valid object is assigned to that.
In this case, it looks like you should modify the vector directly to avoid copying.
void int_part(int sum, vector<vector<int>>& res)
{
vector<int> xs = vector<int>{sum};
int current_sum = sum;
while (true)
{
current_sum = accumulate(xs.begin(), xs.end(), 0); //
if (current_sum == sum)
{
res.push_back(xs); //
vector<int> next_xs;
vector<int>::iterator it = find(xs.begin(), xs.end(), 1); //
if (it == xs.begin()) return; //
xs.erase(it, xs.end());
xs[xs.size() - 1] -= 1; //
}
else
{
int tail = xs.back(); //
int diff = sum - current_sum;
int m = std::min(tail, sum - tail);
int next_tail = current_sum m > sum ? diff : m;
xs.push_back(next_tail); //
}
}
}
CodePudding user response:
if (current_sum == sum)
{
// ...
vector<int> next_xs;
As you can see here: next_xs
is declared inside the if
statement. When the if
statement finishes, next_xs
gets destroyed. That's how locally-declared object, in automatic scope, work.
xs = &next_xs;
A pointer to this object is saved here. Immediately afterwards the if
statement ends, and next_xs
gets destroyed.
You end up with a pointer to a destroyed object. Subsequent code attempts to dereference it, and access the destroyed object. This results in undefined behavior, and that's the reason for the crash.