首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

屡次使用malloc函数为什么不行

2013-08-09 
多次使用malloc函数为什么不行?编了一个程序,其中要用到很多很多数组来进行大型的矩阵计算(使用分治法递归

多次使用malloc函数为什么不行?
编了一个程序,
其中要用到很多很多数组来进行大型的矩阵计算(使用分治法递归实现,所以中间数据特别多)。

定义成静态数组已经不够用了(经测试只能支持到几百*几百的数组相乘)。
所以采用了malloc的形式,
但在运行的时候,却出现 Segmentation fault (core dumped)

经测试发现,如果我连续malloc两三次的话,程序是可以运行的,
一旦我连续malloc好多次,程序在运行的时候在某个malloc处就会出错而终止。尽管我测试的矩阵很小,不可能内存不够。

程序本身应该是没有问题的,因为若使用静态数组的话,一切正常。

这样的问题,可能是出在哪里呢?


void STRASSEN(arg)
struct thread_args *arg;
 {
    float **A12,**A21;
    float **B12,**B21;
    float **C11,**C12,**C21,**C22;
    float **MM1,**MM2;
    struct thread_args thread[7];
    int i,j;
    int n = arg->n;
    int m = n/2;

    if (n == TN) {
        MATRIX_MULTIPLY(n,arg->A,arg->B,arg->C);
    } else {

        A12=(float **)malloc(m*sizeof(float *));
        A21=(float **)malloc(m*sizeof(float *));
        B12=(float **)malloc(m*sizeof(float *));
        B21=(float **)malloc(m*sizeof(float *));
        C11=(float **)malloc(m*sizeof(float *));
        C12=(float **)malloc(m*sizeof(float *));
        C21=(float **)malloc(m*sizeof(float *));
        C22=(float **)malloc(m*sizeof(float *));
        MM1=(float **)malloc(m*sizeof(float *));
        MM2=(float **)malloc(m*sizeof(float *));
        if (NULL==A12||NULL==A21||NULL==B12||NULL==B21){
                _error(ERR_MEM);
        }
        if (NULL==C11||NULL==C12||NULL==C21||NULL==C22||NULL==MM1||NULL==MM2) {
                _error(ERR_MEM);
        }
        for (i=0;i<m;i++) {
                A12[i]=(float *)malloc(m*sizeof(float));


                A21[i]=(float *)malloc(m*sizeof(float));
                B12[i]=(float *)malloc(m*sizeof(float));
                B21[i]=(float *)malloc(m*sizeof(float));
                C11[i]=(float *)malloc(m*sizeof(float));
                C12[i]=(float *)malloc(m*sizeof(float));
                C21[i]=(float *)malloc(m*sizeof(float));
                C22[i]=(float *)malloc(m*sizeof(float));
                MM1[i]=(float *)malloc(m*sizeof(float));
                MM2[i]=(float *)malloc(m*sizeof(float));
                if (NULL==A12[i]||NULL==A21[i]||NULL==B12[i]||NULL==B21[i]||NULL==C11[i]||NULL==C12[i]||NULL==C21[i]||NULL==C22[i]||NULL==MM1[i]||NULL==MM2[i]) {
                        _error(ERR_MEM);
                }
      }

  //省略计算各矩阵的步骤
  // 分线程再次调用STRASSEN, 传入的参数thread[i]中包含了float **A,**B,**C,分别也是一个动态分配的二位数组
    for (i = 0; i < 7; i++) {
      pthread_t id;
      if(pthread_create(&id,NULL,(void*)STRASSEN,(void*)&thread[i])) {
        perror("pthread_create");
        exit(1);
      }
      pthread_join(id,NULL);
    }

//省略一些


    for (i=0;i<m;i++) {
        free(A12[i]);
        free(A21[i]);
        free(B12[i]);
        free(B21[i]);
        free(C11[i]);
        free(C12[i]);


        free(C21[i]);
        free(C22[i]);
        free(MM1[i]);
        free(MM2[i]);
    }
    free(A12),free(A21),free(B12),free(B21);
    free(C11),free(C12),free(C21),free(C22),free(MM1),free(MM2);
    }
}



[解决办法]
Segmentation   fault——段错误
解释:A segmentation fault (often shortened to segfault) is a particular error condition that can occur during the operation of computer software. In short, a segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (e.g., attempts to write to a read-only location, or to overwrite part of the operating system). Systems based on processors like the Motorola 68000 tend to refer to these events as Address or Bus errors.

Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.

On Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.



翻译为:
所谓的段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation fault就出现了

楼主参考。

[解决办法]
段错误一般为指针错误,你可以使用GDB模式调试,当程序崩溃后使用bt,看下在什么地方出的问题。
[解决办法]
程序本身应该是没有问题的,因为若使用静态数组的话,一切正常。 
  这个不一定,因为某些内存泄露和越界是程序运行中无法发现的,所以可能的问题还是程序的问题
还是要通过分析程序及利用调试工具来发现程序中的错误

[解决办法]
如果用gdb调试的话,可以看出段错误发生在哪一行代码上
[解决办法]


int get_mem_for_data(int x, int y, double*** data)
{
if(NULL == (*data = (double**)malloc(x*sizeof(double*))))return (-1);
for(int i = 0; i < x; i++)
(*data)[i] = (double*)malloc(y*sizeof(double));
static int k = 0;
printf("%d\n", k++);
return (0);
}

int main(int argc, char* argv[])
{
printf("Hello World!\n");
double** data[1000];
for(int i = 0; i < 1000; i++)
get_mem_for_data(100, 100, &data[i]);
data[999][99][99] = 1.0;
printf("%f\n", data[999][99][99]);
//释放内存你,略。
return 0;
}
调用了999次,也没问题啊?

[解决办法]
既然静态数组可行,malloc肯定没问题

段错误一般来说 就是指针操作错误,要么释放了无效指针,要么是对无效指针进行操作,再要么是越界

建议你gdb 单步调试走一遍,问题可能不在这个函数里面
[解决办法]
应该是内存操作的问题,也就是指针。

或者是内存分配错误。

希望可以帮到你!

热点排行