free()函数导致运行时错误

时间:2014-04-26 05:47:33

标签: c free dynamic-memory-allocation

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

int *seperateDigits(int n)
{
    int *digits, numberOfDigits = 0, temp = n;

    while (temp) {
        temp /= 10;
        numberOfDigits++;
    }

    digits = (int *)malloc(sizeof(int) * (numberOfDigits + 1));

    digits[numberOfDigits] = -1;
    while (numberOfDigits >= 0) {
        digits[--numberOfDigits] = n % 10;
        n /= 10;
    }

    return digits;
}

int main(void) {
    int n, *na;

    scanf("%d", &n);
    na = seperateDigits(n);

    if (!na) {
        printf("Cannot allocate memory!\n");
        return 1;
    }

    while (*na != -1)
        printf("%d ", *na++);

    free(na);

    return 0;
}

我写了一个函数来将数字分成数字。当我不释放内存时,Everthing工作正常;但是当我尝试使用free()函数释放动态分配的内存时,我收到运行时错误。我做错了什么?

3 个答案:

答案 0 :(得分:3)

你增加na,所以你没有释放malloc返回的内容(但指针numberOfDigits放置它)。改为使用显式整数索引。

哦,不要将malloc()的返回值强制转换为int *it's harmful

答案 1 :(得分:2)

free函数必须传递malloc返回的指针。但是,后增量运算符会更改naprintf调用中main的值{/ p>

printf("%d ", *na++); 

此外,您应在致电malloc后立即查看NULL malloc的返回值。不要施放malloc的结果。如果您忘记包含包含其原型的标题stdlib.h,它可能会导致问题。阅读本文 - Do I cast the result of malloc?我建议进行以下更改 -

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

int *seperateDigits(int n)
{
    int *digits, numberOfDigits = 0, temp = n;

    while (temp) {
        temp /= 10;
        numberOfDigits++;
    }

    // don't cast the result of malloc
    digits = malloc((numberOfDigits + 1) * sizeof(*digits));

    // check the result of malloc just after calling it
    if(digits == NULL) {
        printf("malloc failed to allocate memory\n");
        return NULL;
    }

    digits[numberOfDigits] = -1;
    while (numberOfDigits >= 0) {
        digits[--numberOfDigits] = n % 10;
        n /= 10;
    }

    return digits;
}

int main(void) {
    int n, *na;
    int i = 0;

    scanf("%d", &n);
    na = seperateDigits(n);

    if(na == NULL)
        return 1;

    while (na[i] != -1) {
        printf("%d ", na[i]);
        i++;
    }

    free(na);

    return 0;
}

答案 2 :(得分:0)

na的后期增量外,您还有另一个问题。要理解它,您需要了解内部的免费工作方式。

你可以注意到free并不会问你指针na指向多少内存,因此它会进行正确的释放并确切地知道它有多少内存。问题是如何自由地了解这些信息。响应是,在内部,当您调用malloc calloc或realloc时,这些函数会分配比您请求的更多的内存,这大致是您分配的数量+有关该内存的信息所需的内存量,尤其是其大小。

为了简单起见,想象一下,如果你Tab=malloc (3*sizeof (int))有一个3个整数的Tab,那么malloc真正做的就是分配4 * sizeof(int)字节的内存,即一个数组Tab0在第一个sizeof(int)字节中有4个整数,即Tab0 [0]它存储你要求的内存大小,即Tab0[0] =3*sizeof (int);然后它返回一个指向下一个3 * sizeof(int)的指针字节即return &Tab0[1];。当调用free (Tab);时,它知道你给它的指针引用了数组的第二个成员,所以它递减它并读取释放它所需的内存量:

int* Tab0=Tab-1;
int memoryToFree=Tab0[0];.

我想要注意的是,我所说的并不完全是什么,只是为了理解为什么会出现运行时错误而过度简化。 通常,为了使用malloc,realloc,calloc和free,你不必理解它们的内部工作方式你需要知道的是你应该只传递malloc realloc或calloc返回的指针。

你所遇到的问题是你访问和更改了内存,你不应该触摸一个对于免费工作正常至关重要的内存:

while (numberOfDigits >= 0) {
    digits[--numberOfDigits] = n % 10;
    n /= 10;
}

当numberOfDigits == 0时 digits[--numberOfDigits] = n % 10;相当于numberOfDigits=-1; digits[-1] = n % 10;。 系统不会将此识别为分段错误,因为您实际拥有malloc分配的内存,并且您更改了存储免费需要正常工作的关键信息的数据。 所以,你可以通过这样做来纠正它:

while (numberOfDigits > 0) {
    digits[--numberOfDigits] = n % 10;
    n /= 10;
}