From 080a90fb5ce667cf6be636343ad1c5309f451340 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 18 Oct 2026 17:22:44 +0000 Subject: [PATCH] Port memory leak and bad free fixes from superlu PR #180 to base files Mirror xiaoyeli/superlu#180 (Fix memory leaks and bad frees) in the precision-generic templates so future extractions carry the fixes: - SRC/xgsisx.base, SRC/xgssvx.base: free the MC64 permutation, the permuted matrix AC and the SLU_NR copy AA on the early returns taken for the lwork == -1 memory query and for a singular factorization. - EXAMPLE/xlinsolx*.base: release the L and U SuperMatrix stores when the factors live in a user-supplied work[] array; xlinsolx2 no longer calls Destroy_SuperNode_Matrix/Destroy_CompCol_Matrix on work[] storage. - TESTING/xdrive.base: always destroy the factors xgssv allocated, free the previous factors before xgssvx refactors with DOFACT or SamePattern, and destroy the work[] stores inside the loop instead of once at the end. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01VjnVBdsXEM3c41ssQ3hFAM --- EXAMPLE/xlinsolx.base | 2 ++ EXAMPLE/xlinsolx1.base | 2 ++ EXAMPLE/xlinsolx2.base | 7 ++++++- EXAMPLE/xlinsolx3.base | 2 ++ SRC/xgsisx.base | 19 ++++++++++++++++++- SRC/xgssvx.base | 14 ++++++++++++++ TESTING/xdrive.base | 25 +++++++++++++++++++------ 7 files changed, 63 insertions(+), 8 deletions(-) diff --git a/EXAMPLE/xlinsolx.base b/EXAMPLE/xlinsolx.base index fc3aa5e..0cc643f 100644 --- a/EXAMPLE/xlinsolx.base +++ b/EXAMPLE/xlinsolx.base @@ -199,6 +199,8 @@ int main(int argc, char *argv[]) Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); } else if ( lwork > 0 ) { + Destroy_SuperMatrix_Store(&L); + Destroy_SuperMatrix_Store(&U); SUPERLU_FREE(work); } diff --git a/EXAMPLE/xlinsolx1.base b/EXAMPLE/xlinsolx1.base index 2ef690f..bf40a87 100644 --- a/EXAMPLE/xlinsolx1.base +++ b/EXAMPLE/xlinsolx1.base @@ -222,6 +222,8 @@ int main(int argc, char *argv[]) Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); } else if ( lwork > 0 ) { + Destroy_SuperMatrix_Store(&L); + Destroy_SuperMatrix_Store(&U); SUPERLU_FREE(work); } diff --git a/EXAMPLE/xlinsolx2.base b/EXAMPLE/xlinsolx2.base index 9991a83..ae9ade1 100644 --- a/EXAMPLE/xlinsolx2.base +++ b/EXAMPLE/xlinsolx2.base @@ -192,9 +192,12 @@ int main(int argc, char *argv[]) StatFree(&stat); Destroy_CompCol_Matrix(&A); Destroy_Dense_Matrix(&B); - if ( lwork >= 0 ) { /* Deallocate storage associated with L and U. */ + if ( lwork == 0 ) { /* Deallocate storage associated with L and U. */ Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); + } else if ( lwork > 0 ) { /* L and U are stored in work[]. */ + Destroy_SuperMatrix_Store(&L); + Destroy_SuperMatrix_Store(&U); } /* ------------------------------------------------------------ @@ -259,6 +262,8 @@ int main(int argc, char *argv[]) Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); } else if ( lwork > 0 ) { + Destroy_SuperMatrix_Store(&L); + Destroy_SuperMatrix_Store(&U); SUPERLU_FREE(work); } diff --git a/EXAMPLE/xlinsolx3.base b/EXAMPLE/xlinsolx3.base index f57e249..3a79321 100644 --- a/EXAMPLE/xlinsolx3.base +++ b/EXAMPLE/xlinsolx3.base @@ -255,6 +255,8 @@ int main(int argc, char *argv[]) Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); } else if ( lwork > 0 ) { + Destroy_SuperMatrix_Store(&L); + Destroy_SuperMatrix_Store(&U); SUPERLU_FREE(work); } diff --git a/SRC/xgsisx.base b/SRC/xgsisx.base index f35614e..6585ebc 100644 --- a/SRC/xgsisx.base +++ b/SRC/xgsisx.base @@ -629,6 +629,13 @@ void if ( lwork == -1 ) { mem_usage->total_needed = *info - A->ncol; + // cleanup prior to returning + if ( perm ) SUPERLU_FREE(perm); + Destroy_CompCol_Permuted(&AC); + if ( A->Stype == SLU_NR ) { + Destroy_SuperMatrix_Store(AA); + SUPERLU_FREE(AA); + } return; } @@ -654,7 +661,17 @@ void } if ( options->PivotGrowth ) { - if ( *info > 0 ) return; + if ( *info > 0 ) { + // cleanup prior to returning + if ( nofact ) { + Destroy_CompCol_Permuted(&AC); + } + if ( A->Stype == SLU_NR ) { + Destroy_SuperMatrix_Store(AA); + SUPERLU_FREE(AA); + } + return; + } /* Compute the reciprocal pivot growth factor *recip_pivot_growth. */ *recip_pivot_growth = @(pre)PivotGrowth(A->ncol, AA, perm_c, L, U); diff --git a/SRC/xgssvx.base b/SRC/xgssvx.base index 6f21d78..d270c30 100644 --- a/SRC/xgssvx.base +++ b/SRC/xgssvx.base @@ -545,6 +545,12 @@ printf("dgssvx: Fact=%4d, Trans=%4d, equed=%c\n", if ( lwork == -1 ) { mem_usage->total_needed = *info - A->ncol; + // cleanup prior to returning + Destroy_CompCol_Permuted(&AC); + if ( A->Stype == SLU_NR ) { + Destroy_SuperMatrix_Store(AA); + SUPERLU_FREE(AA); + } return; } } @@ -555,6 +561,14 @@ printf("dgssvx: Fact=%4d, Trans=%4d, equed=%c\n", rank-deficient (*info) columns of A. */ *recip_pivot_growth = @(pre)PivotGrowth(*info, AA, perm_c, L, U); } + // cleanup prior to returning + if ( nofact ) { + Destroy_CompCol_Permuted(&AC); + } + if ( A->Stype == SLU_NR ) { + Destroy_SuperMatrix_Store(AA); + SUPERLU_FREE(AA); + } return; } diff --git a/TESTING/xdrive.base b/TESTING/xdrive.base index 560899a..1067571 100644 --- a/TESTING/xdrive.base +++ b/TESTING/xdrive.base @@ -410,10 +410,9 @@ int main(int argc, char *argv[]) /* Restore perm_c. */ for (i = 0; i < n; ++i) perm_c[i] = pc_save[i]; - if (lwork == 0) { - Destroy_SuperNode_Matrix(&L); - Destroy_CompCol_Matrix(&U); - } + /* @(pre)gssv allocated the factors */ + Destroy_SuperNode_Matrix(&L); + Destroy_CompCol_Matrix(&U); } /* if .. end of testing @(pre)gssv */ /*---------------- @@ -427,6 +426,19 @@ int main(int argc, char *argv[]) @(pre)laqgs(&A, R, C, rowcnd, colcnd, amax, equed); } + /* @(pre)gssvx computes new factors for DOFACT and + SamePattern; free those of the previous call. */ + if ( itran > 0 && (options.Fact == DOFACT || + options.Fact == SamePattern) ) { + if ( lwork == 0 ) { + Destroy_SuperNode_Matrix(&L); + Destroy_CompCol_Matrix(&U); + } else { /* L and U are stored in work[] */ + Destroy_SuperMatrix_Store(&L); + Destroy_SuperMatrix_Store(&U); + } + } + /* Solve the system and compute the condition number and error bounds using @(pre)gssvx. */ @(pre)gssvx(&options, &A, perm_c, perm_r, etree, @@ -491,6 +503,9 @@ int main(int argc, char *argv[]) if ( lwork == 0 ) { Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); + } else { /* L and U are stored in work[] */ + Destroy_SuperMatrix_Store(&L); + Destroy_SuperMatrix_Store(&U); } } /* for equil ... */ @@ -536,8 +551,6 @@ int main(int argc, char *argv[]) #endif if ( lwork > 0 ) { SUPERLU_FREE (work); - Destroy_SuperMatrix_Store(&L); - Destroy_SuperMatrix_Store(&U); } return (nfail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;