Skip to content

Conversation

@vineetbansal
Copy link
Contributor

Thanks to @XiDianZuoYun for bringing this to our attention through issue 198.

Getting the the .solution property of a PyOSQPSolver calls .get_solution(), which in turn does this:

    PyOSQPSolution* solution = new PyOSQPSolution(*this->_solver->solution, this->m, this->n);
    return *solution;

This created a new PyOSQPSolution on the heap every time it was called and returned a reference to it. Since ownership was never transferred and the pointer was never stored, this leaked memory on every call.

The solution is now cached using a std::unique_ptr member variable. The object is created once on first access and automatically cleaned up in PyOSQPSolvers destructor (which calls osqp_cleanup).

Another unrelated memory leak was related to:

this->_solver = new OSQPSolver();

The actual solver is allocated elsewhere (by osqp_setup), so this allocation was unnecessary and would have leaked.

I've tested out the fixes using valgrind on a script that repeatedly access .solution. Something like this:

    for i in range(iterations):
        _ = prob._solver.solution.x
        _ = prob._solver.solution.y

While this was leaking memory in the original implementation, the leak is fixed with this bug.

@vineetbansal vineetbansal requested a review from imciner2 January 20, 2026 03:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants