【问题标题】:Using free() creates segmentation fault使用 free() 会产生分段错误
【发布时间】:2012-11-29 17:52:48
【问题描述】:

我遇到了一个似乎无法通过内存分配解决的问题。

我使用 malloc 创建了 3 个动态分配的数组 (ipiv,k,b),但是当我尝试释放它们时,我遇到了 seg 错误。如果我不释放它们,代码可以正常工作(但如果我运行太多迭代,我会耗尽内存)。

这里是代码...我已经取出了所有不使用 3 个数组的部分,因为代码很长。

#include<stdio.h>
#include <string.h>
#include<stdlib.h>
#include<math.h>
#include <mpi.h>
#include "mkl.h"

#define K(i,j) k[(i)+(j)*(n)]

void dgesv_( const MKL_INT* n, const MKL_INT* nrhs, double* a,
            const MKL_INT* lda, MKL_INT* ipiv, double* b, 
            const MKL_INT* ldb, MKL_INT* info );

int main()
{
    int *ipiv=malloc(n*sizeof(int));
    for (i=0; i<n; i++) {
        ipiv[i]=0;
    }

    for (globloop=0; globloop<=lasti; globloop++) {

        double a[ndofs];
        double rhs[ndofs];
        double F[ndofs];

        double *k=malloc(n*n*sizeof(double));


        //var for stiffness matrix (this is the one acutally fed to dgesv) 
            //see define at top
        for (i=0; i<n; i++) {
            for (j=0; j<n; j++) {
                K(i,j)=0.0;
            }
        }   

            //bunch of stuff modified, a,rhs,and F filled... ect

        while (sos>=ep && nonlinloop<=maxit) {

            double KFull[ndofs][ndofs];
            for (i=0; i<ndofs; i++) {
                for (j=0; j<ndofs; j++) {
                    KFull[i][j]=0.0;
                }
            }

                    //KFull filled with values..

            //trim the arrays to account for bcs 
            double *b=malloc(n*sizeof(double));
            for (i=0; i<n; i++) {
                b[i]=rhs[i+2];
            }

            //k array filled
                    //see define above
            for (i=0; i<n; i++) {
                for (j=0; j<ndofs-2; j++) {
                    K(i,j)=KFull[i+2][j+2];
                }
            }

            //SOLVER
            dgesv_(&n,&one,k,&n,ipiv,b,&n,&info);

            //now we must take our solution in b, and place back into rhs
            for (i=0; i<n; i++) {
                rhs[i+2]=b[i];
            }
            nonlinloop++;
            free(b);
        }
        free(k);
    }
    free(ipiv);
    return 0;
}

释放这三个变量中的任何一个都会导致分段错误。我对此感到非常困惑。

【问题讨论】:

  • 用 valgrind 运行它,它会告诉你出了什么问题。
  • 有没有可能ndofs-2 大于n
  • 不,它们被专门设置为 n=ndofs-4。
  • 我知道这并不能解决您的问题,但为了性能起见,我将在所有循环之外仅分配所有三个数组并重用它们。它们的大小似乎与迭代无关,您在每个循环结束时将其丢弃。只有在两种情况下您才真正需要动态内存:您打算在函数范围之间传输它,或者它太大而无法放入堆栈。堆栈位于非嵌入式系统中,通常为 2-8Mb。如果您的数组适合堆栈,我什至会将它们放在那里。
  • 另一件事:你确定dgesv_ 还没有释放它们吗?在一个已经被释放的指针上调用free通常是一个SIGSEGV

标签: c segmentation-fault malloc free


【解决方案1】:

如果 n=ndofs-4(如 OP 评论中所述)则 ndofs-2 大于 n。然后代码将破坏内存在

K(i,j)=KFull[i+2][j+2];

因为j 运行到ndofs-2-1 并且K (仅)定义为K[0..n-1][0..n-1]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2016-05-18
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多