动态数组分配,按值传递,超出范围
Dynamic Array Allocation, pass by value, out of range
我有两个关于动态分配数组的问题。我已经查找了一些类似的问题,但仍然没有找到答案。
按值传递
基本上,我写了两个函数,一个用于分配内存,另一个用于释放内存。当我按值传递数组指针时,分配函数不起作用(如预期的那样)但自由函数起作用。以我天真的理解,即使我们按值传递数组指针,分配也应该仍然有效,因为它在与所表示的值相同的内存地址分配内存。如果我们稍后引用该地址,无论变量名称如何,我们都应该能够找到 space。这是代码:
void main()
{
int * array;
allocation(array);
deallocation(array);
}
void allocation(int * result)
{
result = malloc(8293 * sizeof(result));
}
void deallocation(int * result)
{
free(result);
}
对于释放测试,我在主函数中声明了 int * array = malloc(23123* sizeof(int)) 而不是使用分配函数。同样,重新分配有效。
超出范围访问。
void main()
{
FILE * fp = fopen("sometext.txt");
int * A = malloc(100 * sizeof(int));
int * B = malloc(200 * sizeof(int));
/* Now I accidentally access A from 0-199 and B from 0-999 using a for loop*/
char buffer[500];
int i,x;
for (i=0; i<200; i++)
{
fgets(fp,buffer);
sccanf(buffer, "%d", x);
A[i]=x;
}
for (i=0; i<1000; i++)
{
fgets(fp,buffer);
sccanf(buffer, "%d", x);
B[i]=x;
}
}
两个 for 循环都不应该工作。但是,我不知何故通过了第一个循环,只在第二个循环中遇到段错误。我得到的错误追溯到 sccanf(我测试了代码,没有给 A 或 B 赋任何值,它工作。所以 sccanf 语句应该没问题。)gdb 错误消息是:isoc99_sscanf(s =, 格式=).
完整的bt消息在下面,SOL[]是我这里的B[],实际的sscanf读取了更多的变量。如果您有兴趣,我可以 post 完整代码。
#0 0x00007ffff7a6869b in _IO_vfscanf_internal (s=s@entry=0x7fffffffd3b0,
format=format@entry=0x4010f8 "%*d%5c%5c%5d %lf %lf %lf %*f %*f %*f\n",
argptr=argptr@entry=0x7fffffffd4d8, errp=errp@entry=0x0) at vfscanf.c:343
#1 0x00007ffff7a72a0c in __GI___isoc99_vsscanf (
string=0x7fffffffd650 " 4545SOL HW123234 2.687 0.089 7.120 -1.1448 0.0920 0.6016\n", format=0x4010f8 "%*d%5c%5c%5d %lf %lf %lf %*f %*f %*f\n",
args=args@entry=0x7fffffffd4d8) at isoc99_vsscanf.c:43
#2 0x00007ffff7a72997 in __isoc99_sscanf (s=<optimized out>,
format=<optimized out>) at isoc99_sscanf.c:31
#3 0x0000000000400a9c in read (PMI=0x603490, COION=0x606ce0,
COUNTERION=0x60dd70, SOL=0x7ffff7f58010, in=0x603010, out=0x603250)
at thick_calc.c:97
#4 0x0000000000400915 in main () at thick_calc.c:52
谢谢!
你没有重新分配指针,应该是
void main()
{
int * array;
allocation(&array);
if (array != NULL)
deallocation(array);
}
void allocation(int **result)
{
if (result == NULL)
return;
*result = malloc(8293 * sizeof(int));
}
void deallocation(int * result)
{
free(result);
}
通过传递指针,你可以修改它的内容,但是你不能改变它指向的地方,所以你必须传递一个指向指针的指针,即指针的地址,这样你才能修改它指向的地方。
您的代码中的问题是您的指针在 main 范围内仍然无效,因此当您将它传递给 free
它实际上并不指向 malloc
ed 内存块。
这样做会导致未定义的行为。读取或写入超过 malloc
ed 块会导致未定义的行为,因此您不能期望给定的行为,因为它是未定义的。
这意味着,它可能会导致分段错误,或者它可以工作,或者任何事情都可能发生,因为它是未定义的。
最终你会写入内存中的一个特殊位置并且会发生一些事情,你无法确定同时发生了什么,因为它又是未定义的行为。
我有两个关于动态分配数组的问题。我已经查找了一些类似的问题,但仍然没有找到答案。
按值传递
基本上,我写了两个函数,一个用于分配内存,另一个用于释放内存。当我按值传递数组指针时,分配函数不起作用(如预期的那样)但自由函数起作用。以我天真的理解,即使我们按值传递数组指针,分配也应该仍然有效,因为它在与所表示的值相同的内存地址分配内存。如果我们稍后引用该地址,无论变量名称如何,我们都应该能够找到 space。这是代码:
void main() { int * array; allocation(array); deallocation(array); } void allocation(int * result) { result = malloc(8293 * sizeof(result)); } void deallocation(int * result) { free(result); }
对于释放测试,我在主函数中声明了 int * array = malloc(23123* sizeof(int)) 而不是使用分配函数。同样,重新分配有效。
超出范围访问。
void main() { FILE * fp = fopen("sometext.txt"); int * A = malloc(100 * sizeof(int)); int * B = malloc(200 * sizeof(int)); /* Now I accidentally access A from 0-199 and B from 0-999 using a for loop*/ char buffer[500]; int i,x; for (i=0; i<200; i++) { fgets(fp,buffer); sccanf(buffer, "%d", x); A[i]=x; } for (i=0; i<1000; i++) { fgets(fp,buffer); sccanf(buffer, "%d", x); B[i]=x; } }
两个 for 循环都不应该工作。但是,我不知何故通过了第一个循环,只在第二个循环中遇到段错误。我得到的错误追溯到 sccanf(我测试了代码,没有给 A 或 B 赋任何值,它工作。所以 sccanf 语句应该没问题。)gdb 错误消息是:isoc99_sscanf(s =, 格式=).
完整的bt消息在下面,SOL[]是我这里的B[],实际的sscanf读取了更多的变量。如果您有兴趣,我可以 post 完整代码。
#0 0x00007ffff7a6869b in _IO_vfscanf_internal (s=s@entry=0x7fffffffd3b0,
format=format@entry=0x4010f8 "%*d%5c%5c%5d %lf %lf %lf %*f %*f %*f\n",
argptr=argptr@entry=0x7fffffffd4d8, errp=errp@entry=0x0) at vfscanf.c:343
#1 0x00007ffff7a72a0c in __GI___isoc99_vsscanf (
string=0x7fffffffd650 " 4545SOL HW123234 2.687 0.089 7.120 -1.1448 0.0920 0.6016\n", format=0x4010f8 "%*d%5c%5c%5d %lf %lf %lf %*f %*f %*f\n",
args=args@entry=0x7fffffffd4d8) at isoc99_vsscanf.c:43
#2 0x00007ffff7a72997 in __isoc99_sscanf (s=<optimized out>,
format=<optimized out>) at isoc99_sscanf.c:31
#3 0x0000000000400a9c in read (PMI=0x603490, COION=0x606ce0,
COUNTERION=0x60dd70, SOL=0x7ffff7f58010, in=0x603010, out=0x603250)
at thick_calc.c:97
#4 0x0000000000400915 in main () at thick_calc.c:52
谢谢!
你没有重新分配指针,应该是
void main() { int * array; allocation(&array); if (array != NULL) deallocation(array); } void allocation(int **result) { if (result == NULL) return; *result = malloc(8293 * sizeof(int)); } void deallocation(int * result) { free(result); }
通过传递指针,你可以修改它的内容,但是你不能改变它指向的地方,所以你必须传递一个指向指针的指针,即指针的地址,这样你才能修改它指向的地方。
您的代码中的问题是您的指针在 main 范围内仍然无效,因此当您将它传递给
free
它实际上并不指向malloc
ed 内存块。这样做会导致未定义的行为。读取或写入超过
malloc
ed 块会导致未定义的行为,因此您不能期望给定的行为,因为它是未定义的。这意味着,它可能会导致分段错误,或者它可以工作,或者任何事情都可能发生,因为它是未定义的。
最终你会写入内存中的一个特殊位置并且会发生一些事情,你无法确定同时发生了什么,因为它又是未定义的行为。