#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()函数释放动态分配的内存时,我收到运行时错误。我做错了什么?
答案 0 :(得分:3)
你增加na
,所以你没有释放malloc返回的内容(但指针numberOfDigits
放置它)。改为使用显式整数索引。
哦,不要将malloc()
的返回值强制转换为int *
。 it's harmful
答案 1 :(得分:2)
free
函数必须传递malloc
返回的指针。但是,后增量运算符会更改na
中printf
调用中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;
}