我见过其他人问这个,但似乎看不到答案,或者问题出在字符或其他问题上。我真的无法弄清楚为什么会出现此错误,因为我正在分配。我的原始代码更长,但我简化为得到错误的原因,并且即将出现完全相同的错误,所以这就是问题所在。
#include <stdio.h>
#include <stdlib.h>
void addInteger(int **iArr, int *newI, int * count);
int main(){
int* iArr = malloc(0);
int iCount = 0;
int newInt = 0;
int i;
for(i=0;i<5;i++){
printf("Enter number: ");
scanf("%d",&newInt);
iCount++;
iArr = realloc(iArr, sizeof(int*) * iCount);
addInteger(&iArr, &newInt, &iCount);
}
free(iArr);
return 0;
}
void addInteger(int **iArr, int *newI, int * count){
iArr[*count-1] = malloc(sizeof(int));
iArr[*count-1] = newI;
}
使用我的输入来运行它会在第二个数字上出现错误:
输入数字:1
输入数字:3
a.out(1291,0x7fffb62df380)malloc:对象0x7ffeed674b78的错误:未分配要重新分配的指针
***在malloc_error_break中设置一个断点进行调试
中止陷阱:6
答案 0 :(得分:1)
您的取消引用存在一些错误:
变量iArr
是指向类型int
的数组的指针。
但是您要将其地址传递到addInteger
,然后用随机输入值替换此地址。
然后,此随机输入值将传递给realloc
而不是您分配的指针,该指针现在消失了。
所以您得到了错误。
让我们修复您的代码来避免这种情况:
//NOTE: there is no need to pass newI and count as pointers, because the function does not change them!
void addInteger(int **iArr, int newI, int count);
int main(){
//1. If you want iArr to be array of pointers, you need to start with ** pointer to pointer
//2. Just initialize with NULL, when realloc gets NULL it works just like malloc
int** iArr = NULL;
int iCount = 0;
int newInt = 0;
int i;
for(i=0;i<5;i++){
printf("Enter number: ");
scanf("%d",&newInt);
iCount++;
iArr = realloc(iArr, sizeof(int*) * iCount);
//You do not need to pass addresses here because your function does not change its parameters
addInteger(iArr, newInt, iCount);
}
free(iArr); //this will cause a memory leak!
//you need to loop over the array and free each integer first.
return 0;
}
void addInteger(int **iArr, int newI, int count){
iArr[count - 1] = malloc(sizeof(int));
*iArr[count - 1] = newI;
/* Note the * here - it is important!
Without it, you would overwrite the pointer you just allocated in the prevoius line
But the * tells the compiler "put the int value at the address specified by the array
*/
}
答案 1 :(得分:0)
让我们一次在程序中执行一个语句。
int* iArr = malloc(0);
iArr
是NULL
或指向大小为0的对象。
int iCount = 0;
int newInt = 0;
int i;
for(i=0;i<5;i++){
在第一次迭代中,我们有i = 0
。
printf("Enter number: ");
scanf("%d",&newInt);
假设用户在此处输入了42
,因此newInt = 42
。
iCount++;
现在iCount = 1
。
iArr = realloc(iArr, sizeof(int*) * iCount);
这很可疑:iArr
被声明为指向int的指针(可以用来指向整数数组),但是您没有为iCount
整数分配空间,重新为iCount
指向int的指针分配空间。
如果iArr
是一个指向int的动态指针数组,则应将其声明为
int ** iArr;
如果iArr
是一个int的动态数组,则此调用应更改为
iArr = realloc(iArr, sizeof (int) * iCount);
或(最好):
iArr = realloc(iArr, sizeof *iArr * iCount);
无论声明如何iArr
,后一种形式总是正确的 1 。
(将NULL
作为第一个参数传递给realloc
很好,所以最初返回的malloc(0)
到底是什么都没关系。)
addInteger(&iArr, &newInt, &iCount);
让我们在此内联此函数(我更改了参数名称以使其更清楚地显示正在发生的事情):
int **addInteger_iArr = &iArr;
int *addInteger_newI = &newInt;
int *addInteger_count = &iCount;
我们初始化函数参数。
addInteger_iArr[*addInteger_count-1] = malloc(sizeof(int));
好的,这行实际上是做什么的?我们知道addInteger_count
的值;是&iCount
,所以我们将其插入:
addInteger_iArr[*(&iCount)-1] = malloc(sizeof(int));
*
和&
互相抵消,给出:
addInteger_iArr[iCount-1] = malloc(sizeof(int));
iCount
是1
,而1-1
是0
,因此变成:
addInteger_iArr[0] = malloc(sizeof(int));
类似地,让我们插入addInteger_iArr
的值,即&iArr
:
(&iArr)[0] = malloc(sizeof(int));
a[b]
由C定义为*(a + b)
,所以此行的意思是:
*(&iArr + 0) = malloc(sizeof(int));
添加0
不会执行任何操作,而*
和&
会互相抵消,所以我们得到:
iArr = malloc(sizeof(int));
嘿!我们刚刚失去了iArr
的旧值(realloc
返回的指针)。这是内存泄漏。
addInteger_iArr[*addInteger_count-1] = addInteger_newI;
赋值的左侧与前面的语句相同; addInteger_newI
与&newInt
相同:
iArr = &newInt;
嘿!我们只是失去了旧值iArr
(上一条语句中malloc
返回的指针)。这是另一次内存泄漏。
此外,iArr
不再指向动态分配的内存;它指向newInt
,它只是一个局部变量。
}
现在,我们开始循环的第二次迭代。这会在realloc(iArr, ...)
中崩溃,因为此时iArr
被设置为&newInt
。
有几种方法可以修复此代码。
如果只需要一个简单的动态整数数组,则应将循环更改为:
iCount++;
iArr = realloc(iArr, iCount * sizeof *iArr);
iArr[iCount-1] = newInt;
如果要将最后一条语句移到函数中,则:
addInteger(iArr, iCount, newInt);
使用
void addInteger(int *iArr, int iCount, int newInt) {
iArr[iCount-1] = newInt;
}
1 嗯,大小计算是正确的。您仍然需要检查realloc
是否失败,在这种情况下它会返回NULL
,并且您需要手动free
指针,并且通常应该检查{{1 }}计算。