单线程循环迭代内存溢出问题排查:为何已释放内存仍耗尽?
Let's break down the issue with your code and fix it step by step.
First, let's recap your scenario: when running the loop with multiple iterations (from 50e6 down to 20e6 in steps of 10e6), you hit a memory overflow and get terminated. But when running a single iteration (minIter = maxIter = 50e6), everything works fine. The key here is hidden memory leaks in your cleanup code—you're only freeing the top-level pointer arrays, not the nested allocations inside them.
The Root Cause: Incomplete Memory Deallocation
Looking at your free calls at the end of the loop:
free(iterationPoints); free(grid); free(normalizedPoints);
Each of these variables is a multi-dimensional array, but you're only freeing the outermost layer. Let's break down each case:
iterationPointsandnormalizedPoints(2D arrays)
You allocate them like this:iterationPoints = (double **) malloc(iterations *sizeof(double *)); for(i = 0; i < iterations; i++){ iterationPoints[i] = (double *) malloc(DIMS *sizeof(double)); }But you only free
iterationPoints—you never free eachiterationPoints[i]that you malloc'd in the loop. This means every loop iteration leaksiterations * DIMS * sizeof(double)bytes of memory.grid(3D array)
For the grid, you do three levels of allocation:grid = (bool ***) malloc(boxesPerDim *sizeof(bool **)); for(j_X = 0; j_X < boxesPerDim; j_X++){ grid[j_X] = (bool **) malloc(boxesPerDim *sizeof(bool *)); for(j_Y = 0; j_Y < boxesPerDim; j_Y++){ grid[j_X][j_Y] = (bool *) calloc(boxesPerDim,sizeof(bool *)); } }But you only free the top-level
gridpointer. The middle layers (grid[j_X]) and innermost layers (grid[j_X][j_Y]) are never freed, leading to massive memory leaks per loop iteration.
Why Single Iteration Works
When you run a single iteration, the process exits after the loop finishes. Modern operating systems automatically reclaim all memory used by a process when it terminates, so the leaked memory doesn't have a chance to accumulate and cause an overflow. But with multiple loop iterations, the leaks pile up every time the loop runs, eventually exceeding your process's memory limit.
Fixed Cleanup Code
Here's how to properly free each multi-dimensional array:
1. Fix iterationPoints cleanup
// Free each inner array first for(i = 0; i < iterations; i++){ free(iterationPoints[i]); } // Then free the top-level pointer array free(iterationPoints); iterationPoints = NULL; // Optional: avoid dangling pointer issues
2. Fix normalizedPoints cleanup
Do the same as above:
for(i = 0; i < iterations; i++){ free(normalizedPoints[i]); } free(normalizedPoints); normalizedPoints = NULL;
3. Fix grid cleanup
You need to free from the innermost layer outwards:
// Free innermost calloc'd arrays for(j_X = 0; j_X < boxesPerDim; j_X++){ for(j_Y = 0; j_Y < boxesPerDim; j_Y++){ free(grid[j_X][j_Y]); } // Free middle-level pointer arrays free(grid[j_X]); } // Free top-level pointer array free(grid); grid = NULL;
Bonus Recommendations
- Wrap allocation/deallocation in helper functions: To avoid repeating this logic and missing cleanup steps, create functions like
allocate_2d_doubleandfree_2d_double, orallocate_3d_boolandfree_3d_bool. This makes your code cleaner and less error-prone. - Check malloc/calloc returns: Always verify that
malloc/callocdoesn't returnNULL—this can help catch out-of-memory conditions early instead of crashing later. - Simplify OpenMP directives: Since you're forcing
num_threads(1), the#pragma omp parallel for orderedandprivateclauses are unnecessary. You can remove them to clean up your code without affecting functionality.
内容的提问来源于stack exchange,提问作者Chopin

