在C中使用free()时出错

时间:2015-02-06 04:37:47

标签: c linux gcc

我正在尝试用C语言编写一个程序,它有一个函数 split_array 。它需要一个指向动态分配的数组的指针,然后将它分成两半,即左右两种。

该程序样本的代码是:

#include<stdio.h>
#include<stdlib.h>

void split_array(int *A, int x)
{
    int *left=NULL, *right=NULL, i, mid=0;

    mid=x/2;
    left=(int*)malloc(sizeof(int)*mid);
        if(left==NULL)
        {
            printf("\nError allocating memory. Aborting!\n\n");
            exit(1);
        }

    if(x%2==0)
    {
            right=(int*)malloc(sizeof(int)*mid);
            if(right==NULL)
            {
                    printf("\nError allocating memory. Aborting!\n\n");
                    exit(1);
            }
    }
    else
    {
        right=(int*)malloc(sizeof(int)*(mid+1));
            if(right==NULL)
            {
                    printf("\nError allocating memory. Aborting!\n\n");
                    exit(1);
            }
    }

        for(i=0;i<mid;i++)
           left[i]=A[i];

        for(i=mid;i<x;i++)
           right[i]=A[i];

        printf("\nleft: ");
        for(i=0;i<mid;i++)
            printf("%d ", left[i]);
        printf("\n");
        printf("\nright: ");
        for(i=mid;i<x;i++)
            printf("%d ", right[i]);
        printf("\n");

    free(left);
    free(right);

    left=NULL;
    right=NULL;
}

int main()
{
    int *arr=NULL, i, l=0;

    printf("Enter number of elements required in array: ");
    scanf("%d", &l);

    arr=(int*)malloc(sizeof(int)*l);
    if(arr==NULL)
    {
        printf("\nError allocating memory. Aborting!\n\n");
        exit(1);
    }

    printf("Enter the elements: ");
    for(i=0;i<l;i++)
        scanf("%d", &arr[i]);

    printf("\nYou entered the elements: ");
    for(i=0;i<l;i++)
        printf("%d ", arr[i]);
    printf("\n");

    split_array(arr, l);

    free(arr);
    arr=NULL;

return 0;
}

只要数组的长度小于或等于6,它就会正常执行。但是当长度大于或等于7时,它会开始抛出错误消息。

输出样本为:

Enter number of elements required in array: 7 Enter the elements: 1 2 3 4 5 6 7

You entered the elements: 1 2 3 4 5 6 7

left: 1 2 3 

right: 4 5 6 7 
*** glibc detected *** ./a.out: free(): invalid next size (fast): 0x0000000002451060 ***
======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(+0x76a16)[0x7f1d2d616a16] /lib/x86left: 1 2 3 

right: 4 5 6 7 
*** glibc detected *** ./a.out: free(): invalid next size (fast): 0x00000_64-linux-gnu/libc.so.6(cfree+0x6c)[0x7f1d2d61b7bc] ./a.out[0x400910] ./a.out[0x400a3e] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x7f1d2d5beead] ./a.out[0x400619]
======= Memory map: ======== 00400000-00401000 r-xp 00000000 08:01 25954902                           /home/ralph/Desktop/a.out 00600000-00601000 rw-p 00000000 08:01 25954902                         /home/ralph/Desktop/a.out 02451000-02472000 rw-p 00000000 00:00 0      [heap] 7f1d28000000-7f1d28021000 rw-p 00000000 00:00 0  7f1d28021000-7f1d2c000000 ---p 00000000 00:00 0  7f1d2d38a000-7f1d2d39f000 r-xp 00000000 08:01 17957772                 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f1d2d39f000-7f1d2d59f000 ---p 00015000 08:01 17957772                   /lib/x86_64-linux-gnu/libgcc_s.so.1 7f1d2d59f000-7f1d2d5a0000 rw-p 00015000 08:01 17957772                   /lib/x86_64-linux-gnu/libgcc_s.so.1 7f1d2d5a0000-7f1d2d722000 r-xp 00000000 08:01 17956950                   /lib/x86_64-linux-gnu/libc-2.13.so 7f1d2d722000-7f1d2d922000 ---p 00182000 08:01 17956950                   /lib/x86_64-linux-gnu/libc-2.13.so 7f1d2d922000-7f1d2d926000 r--p 00182000 08:01 17956950                   /lib/x86_64-linux-gnu/libc-2.13.so 7f1d2d926000-7f1d2d927000 rw-p 00186000 08:01 17956950                   /lib/x86_64-linux-gnu/libc-2.13.so 7f1d2d927000-7f1d2d92c000 rw-p 00000000 00:00 0  7f1d2d92c000-7f1d2d94c000 r-xp 00000000 08:01 17957749                   /lib/x86_64-linux-gnu/ld-2.13.so 7f1d2db2c000-7f1d2db2f000 rw-p 00000000 00:00 0  7f1d2db47000-7f1d2db4b000 rw-p 00000000 00:00 0  7f1d2db4b000-7f1d2db4c000 r--p 0001f000 08:01 17957749                 /lib/x86_64-linux-gnu/ld-2.13.so 7f1d2db4c000-7f1d2db4d000 rw-p 00020000 08:01 17957749                   /lib/x86_64-linux-gnu/ld-2.13.so 7f1d2db4d000-7f1d2db4e000 rw-p 00000000 00:00 0  7fff59345000-7fff59366000 rw-p 00000000 00:00 0      [stack]

7fff593ff000-7fff59400000 r-xp 00000000 00:00 0                        [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0         [vsyscall] Aborted

我正在使用GNU / Linux amd64和gcc 4.7.2。关于为什么会发生这种情况的任何说明?

由于

2 个答案:

答案 0 :(得分:5)

这些行

for(i=mid;i<x;i++)
   right[i]=A[i];

和这些行

for(i=mid;i<x;i++)
   printf("%d ", right[i]);

错了。您正在访问right越界,并导致未定义的行为。

他们需要:

for(i=mid;i<x;i++)
   right[i-mid]=A[i];

for(i=mid;i<x;i++)
   printf("%d ", right[i-mid]);

答案 1 :(得分:3)

您正在复制到right数组中的错误区域,或者(更确切地说)您要复制到为right数组分配的空间之外。你的循环是:

for(i=mid;i<x;i++)
   right[i]=A[i];

需要:

for (i = mid; i < x; i++)
    right[i-mid] = A[i];

印刷循环存在同等问题,应写成:

for (i = mid; i < x; i++)
    printf("%d ", right[i - mid]);

您还应该查看代码:

if(x%2==0)
{
    right=(int*)malloc(sizeof(int)*mid);
    if(right==NULL)
    {
        printf("\nError allocating memory. Aborting!\n\n");
        exit(1);
    }
}
else
{
    right=(int*)malloc(sizeof(int)*(mid+1));
    if(right==NULL)
    {
        printf("\nError allocating memory. Aborting!\n\n");
        exit(1);
    }
}

这应该是一个巨大的重复:

int rsize = x - mid;
right = (int*)malloc(sizeof(*right)* rsize);
if(right==NULL)
{
    printf("\nError allocating memory. Aborting!\n\n");
    exit(1);
}

有了这个,您还可以将循环重写为:

for (i = 0; i < rsize; i++)
    right[i] = A[i + mid];

for (i = 0; i < rsize; i++)
    printf("%d ", right[i]);

有些人会因casting the return from malloc()而鞭挞你。