Home > Back-end >  C error: "pointer being freed was not allocated"
C error: "pointer being freed was not allocated"

Time:06-06

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.

  • Related