Calloc 在不同计算机上的行为不同
Calloc behaves differently on different computers
我用C写了下面的代码:
#include <stdio.h>
#include <stdlib.h>
int func(int n, int * data){
for(int i = 1; i <= n; i++){
data = realloc(data, i * sizeof(int));
data[i - 1] = i;
}
return 0;
}
int main(void){
int numb = 10;
int * array = calloc(1, sizeof(int));
func(numb, array);
for(int j = 0; j < numb; j++){
printf("%d \t", array[j]);
}
free(array);
return 0;
}
在第一台计算机上,输出符合预期:
1 2 3 4 5 6 7 8 9 10
现在,如果我在另一台计算机上编译并 运行 同一程序,它会输出随机整数值。我在这里错过了什么?我做错了什么?为什么同一个程序在不同的计算机上有不同的行为?
此程序的行为未定义。如果它在任何计算机上打印出您期望的结果,那纯属巧合。
int * array = calloc(1, sizeof(int));
func(numb, array);
您在此处按值 传递array
,这意味着func
对其所做的任何操作对于外部范围都是不可见的。请注意 realloc
不保证 return 是同一个指针,因此您需要预料到 array
会在调用过程中发生变化。尝试将指针传递给 array
。
int func(int n, int ** data){
for(int i = 1; i <= n; i++){
*data = realloc(*data, i * sizeof(int));
(*data)[i - 1] = i;
}
return 0;
}
...
func(numb, &array);
根据 Ian Abbot 的评论,您可以做的最小修正是 func()
return 新分配的块:
#include <stdio.h>
#include <stdlib.h>
int * func(int n, int * data) // <-- Notice the * in the return value
{
for(int i = 1; i <= n; i++){
data = realloc(data, i * sizeof(int));
data[i - 1] = i;
}
return data; // <-- We return a pointer to the newly allocated memory block
}
int main(void)
{
int numb = 10;
int * array = calloc(1, sizeof(int));
array = func(numb, array); // <-- reassign to array (same pattern as realloc)
for(int j = 0; j < numb; j++){
printf("%d \t", array[j]);
}
free(array);
return 0;
}
通过这种方式,您可以确定如果 realloc()
更改了内存块的位置,它会在数组中更新。
您的程序有未定义的行为。所以,即使在同一台计算机上,它也有可能有不同的行为......让我解释一下:
#include <stdio.h>
#include <stdlib.h>
int func(int n, int * data){
for(int i = 1; i <= n; i++){
// HERE, YOU CHANGE THE VALUE OF data FOR THE NEW
// VALUE RETURNED BY REALLOC. As the value ov array
// was copied on entry, it is not known outside of
// func()
data = realloc(data, i * sizeof(int));
data[i - 1] = i;
}
return 0;
// AFTER THIS POINT THE ORIGINAL (the passed in value
// to func() is not valid anymore
}
int main(void){
int numb = 10;
int * array = calloc(1, sizeof(int));
func(numb, array);
// at this point, the value of array is not valid,
// in case the value realloc() has returned inside
// func() has changed.
for(int j = 0; j < numb; j++){
printf("%d \t", array[j]);
}
// THIS IS ALSO INCORRECT.
free(array);
return 0;
}
您的问题的解决方法是 return
返回新值(由 calloc() 编辑的 return),如
#include <stdio.h>
#include <stdlib.h>
int *func(int n, int * data){
for(int i = 1; i <= n; i++){
data = realloc(data, i * sizeof(int));
data[i - 1] = i;
}
return data;
}
int main(void){
int numb = 10;
int * array = calloc(1, sizeof(int));
// now array continues to be bvalid after the call to func().
array = func(numb, array);
for(int j = 0; j < numb; j++){
printf("%d \t", array[j]);
}
free(array);
return 0;
}
顺便说一下,为了达到最优,并且如您所知,i
将采用 func()
(n
)的最终值,您应该写成 func()
使 只调用一次 realloc()
,这比每个值重新分配一次要快。
int *func(int n, int *data) {
data = realloc(data, n * sizeof *data);
for (int i = 1; i <= n; i++)
data[i-1] = i;
return data;
}
我用C写了下面的代码:
#include <stdio.h>
#include <stdlib.h>
int func(int n, int * data){
for(int i = 1; i <= n; i++){
data = realloc(data, i * sizeof(int));
data[i - 1] = i;
}
return 0;
}
int main(void){
int numb = 10;
int * array = calloc(1, sizeof(int));
func(numb, array);
for(int j = 0; j < numb; j++){
printf("%d \t", array[j]);
}
free(array);
return 0;
}
在第一台计算机上,输出符合预期:
1 2 3 4 5 6 7 8 9 10
现在,如果我在另一台计算机上编译并 运行 同一程序,它会输出随机整数值。我在这里错过了什么?我做错了什么?为什么同一个程序在不同的计算机上有不同的行为?
此程序的行为未定义。如果它在任何计算机上打印出您期望的结果,那纯属巧合。
int * array = calloc(1, sizeof(int));
func(numb, array);
您在此处按值 传递array
,这意味着func
对其所做的任何操作对于外部范围都是不可见的。请注意 realloc
不保证 return 是同一个指针,因此您需要预料到 array
会在调用过程中发生变化。尝试将指针传递给 array
。
int func(int n, int ** data){
for(int i = 1; i <= n; i++){
*data = realloc(*data, i * sizeof(int));
(*data)[i - 1] = i;
}
return 0;
}
...
func(numb, &array);
根据 Ian Abbot 的评论,您可以做的最小修正是 func()
return 新分配的块:
#include <stdio.h>
#include <stdlib.h>
int * func(int n, int * data) // <-- Notice the * in the return value
{
for(int i = 1; i <= n; i++){
data = realloc(data, i * sizeof(int));
data[i - 1] = i;
}
return data; // <-- We return a pointer to the newly allocated memory block
}
int main(void)
{
int numb = 10;
int * array = calloc(1, sizeof(int));
array = func(numb, array); // <-- reassign to array (same pattern as realloc)
for(int j = 0; j < numb; j++){
printf("%d \t", array[j]);
}
free(array);
return 0;
}
通过这种方式,您可以确定如果 realloc()
更改了内存块的位置,它会在数组中更新。
您的程序有未定义的行为。所以,即使在同一台计算机上,它也有可能有不同的行为......让我解释一下:
#include <stdio.h>
#include <stdlib.h>
int func(int n, int * data){
for(int i = 1; i <= n; i++){
// HERE, YOU CHANGE THE VALUE OF data FOR THE NEW
// VALUE RETURNED BY REALLOC. As the value ov array
// was copied on entry, it is not known outside of
// func()
data = realloc(data, i * sizeof(int));
data[i - 1] = i;
}
return 0;
// AFTER THIS POINT THE ORIGINAL (the passed in value
// to func() is not valid anymore
}
int main(void){
int numb = 10;
int * array = calloc(1, sizeof(int));
func(numb, array);
// at this point, the value of array is not valid,
// in case the value realloc() has returned inside
// func() has changed.
for(int j = 0; j < numb; j++){
printf("%d \t", array[j]);
}
// THIS IS ALSO INCORRECT.
free(array);
return 0;
}
您的问题的解决方法是 return 返回新值(由 calloc() 编辑的 return),如
#include <stdio.h>
#include <stdlib.h>
int *func(int n, int * data){
for(int i = 1; i <= n; i++){
data = realloc(data, i * sizeof(int));
data[i - 1] = i;
}
return data;
}
int main(void){
int numb = 10;
int * array = calloc(1, sizeof(int));
// now array continues to be bvalid after the call to func().
array = func(numb, array);
for(int j = 0; j < numb; j++){
printf("%d \t", array[j]);
}
free(array);
return 0;
}
顺便说一下,为了达到最优,并且如您所知,i
将采用 func()
(n
)的最终值,您应该写成 func()
使 只调用一次 realloc()
,这比每个值重新分配一次要快。
int *func(int n, int *data) {
data = realloc(data, n * sizeof *data);
for (int i = 1; i <= n; i++)
data[i-1] = i;
return data;
}