在 while 循环和重新分配期间将带有 scanf 的整数放入内存分配中
Taking ints with scanf into a memory allocation during a while loop and realloc'ing
我声明了一个int指针并给它分配内存。然后我将整数输入其中,直到用户输入 Ctrl+d。除非我尝试输入 7 或更多,否则循环工作正常,此时它会给我一个看起来像 "realloc(): invalid next size" 的错误并给我一个 backtrace/memory 映射。它必须与我的 realloc
行有关,但我不确定是什么。有没有大佬可以解惑一下?
int n= 0, *x, i;
double mean = 0.0, median = 0.0, stdDev = 0.0;
x = malloc(sizeof(int));
for(i = 0; scanf("%d", &x[i]) != -1; i++) {
n++;
x = realloc(x, n+1 * sizeof(int));
mean = findMean(x, n);
median = findMedian(x, n);
stdDev = findStandardDeviation(x, n, mean);
}
n+1 * sizeof(int)
与 (n+1) * sizeof(int)
不同
问题是运算顺序:n + 1 * sizeof(int)
表示 "multiply 1 times the sizeof(int), then add n"。您可以使用括号来强制执行顺序:(n + 1) * sizeof(int)
.
内存分配可能很昂贵!请求一个合理的内存块,然后每隔一段时间将它增加一个因子,比如 2。在内存分配系统调用中,OS 可能会给你一个比你请求的更大的块,以便随后的 realloc
调用成本更低,并且使用您的程序已经可用的内存。
最好检查一下您的 malloc
和 realloc
调用是否成功。如果分配请求失败,这些函数 return NULL。
此外,不要忘记 free
完成分配的内存以避免内存泄漏。
编写自己的类似于 "vector/ArrayList/list" 的界面可能是一个有趣的练习,该界面可以根据大小扩展和收缩,并可能具有 slice(start_index, end_index)
和 remove(index)
等操作。
这是一个完整的例子:
#include <stdio.h>
#include <stdlib.h>
int main() {
int nums_len = 0;
int nums_capacity = 5;
int *nums = malloc(nums_capacity * sizeof(int));
while (scanf("%d", &nums[nums_len]) != -1) {
if (++nums_len >= nums_capacity) {
printf("increasing capacity from %d to %d\n",
nums_capacity, nums_capacity * 2);
nums_capacity *= 2;
nums = realloc(nums, nums_capacity * sizeof(int));
if (!nums) {
fprintf(stderr, "%s: %d: realloc failed\n",
__func__, __LINE__);
exit(1);
}
}
printf("got: %d\n", nums[nums_len-1]);
}
printf("Here are all of the %d numbers you gave me:\n", nums_len);
for (int i = 0; i < nums_len; i++) {
printf("%d ", nums[i]);
}
puts("");
free(nums);
return 0;
}
样本运行:
5
got: 5
6
got: 6
7
got: 7
8
got: 8
1
increasing capacity from 5 to 10
got: 1
3
got: 3
5
got: 5
6
got: 6
7
got: 7
1
increasing capacity from 10 to 20
got: 1
2
got: 2
3
got: 3
4
got: 4
5
got: 5
6
got: 6
67
got: 67
8
got: 8
1
got: 1
2
got: 2
3
increasing capacity from 20 to 40
got: 3
4
got: 4
1
got: 1
2
got: 2
Here are all of the 23 numbers you gave me:
5 6 7 8 1 3 5 6 7 1 2 3 4 5 6 67 8 1 2 3 4 1 2
我声明了一个int指针并给它分配内存。然后我将整数输入其中,直到用户输入 Ctrl+d。除非我尝试输入 7 或更多,否则循环工作正常,此时它会给我一个看起来像 "realloc(): invalid next size" 的错误并给我一个 backtrace/memory 映射。它必须与我的 realloc
行有关,但我不确定是什么。有没有大佬可以解惑一下?
int n= 0, *x, i;
double mean = 0.0, median = 0.0, stdDev = 0.0;
x = malloc(sizeof(int));
for(i = 0; scanf("%d", &x[i]) != -1; i++) {
n++;
x = realloc(x, n+1 * sizeof(int));
mean = findMean(x, n);
median = findMedian(x, n);
stdDev = findStandardDeviation(x, n, mean);
}
n+1 * sizeof(int)
与 (n+1) * sizeof(int)
问题是运算顺序:n + 1 * sizeof(int)
表示 "multiply 1 times the sizeof(int), then add n"。您可以使用括号来强制执行顺序:(n + 1) * sizeof(int)
.
内存分配可能很昂贵!请求一个合理的内存块,然后每隔一段时间将它增加一个因子,比如 2。在内存分配系统调用中,OS 可能会给你一个比你请求的更大的块,以便随后的 realloc
调用成本更低,并且使用您的程序已经可用的内存。
最好检查一下您的 malloc
和 realloc
调用是否成功。如果分配请求失败,这些函数 return NULL。
此外,不要忘记 free
完成分配的内存以避免内存泄漏。
编写自己的类似于 "vector/ArrayList/list" 的界面可能是一个有趣的练习,该界面可以根据大小扩展和收缩,并可能具有 slice(start_index, end_index)
和 remove(index)
等操作。
这是一个完整的例子:
#include <stdio.h>
#include <stdlib.h>
int main() {
int nums_len = 0;
int nums_capacity = 5;
int *nums = malloc(nums_capacity * sizeof(int));
while (scanf("%d", &nums[nums_len]) != -1) {
if (++nums_len >= nums_capacity) {
printf("increasing capacity from %d to %d\n",
nums_capacity, nums_capacity * 2);
nums_capacity *= 2;
nums = realloc(nums, nums_capacity * sizeof(int));
if (!nums) {
fprintf(stderr, "%s: %d: realloc failed\n",
__func__, __LINE__);
exit(1);
}
}
printf("got: %d\n", nums[nums_len-1]);
}
printf("Here are all of the %d numbers you gave me:\n", nums_len);
for (int i = 0; i < nums_len; i++) {
printf("%d ", nums[i]);
}
puts("");
free(nums);
return 0;
}
样本运行:
5
got: 5
6
got: 6
7
got: 7
8
got: 8
1
increasing capacity from 5 to 10
got: 1
3
got: 3
5
got: 5
6
got: 6
7
got: 7
1
increasing capacity from 10 to 20
got: 1
2
got: 2
3
got: 3
4
got: 4
5
got: 5
6
got: 6
67
got: 67
8
got: 8
1
got: 1
2
got: 2
3
increasing capacity from 20 to 40
got: 3
4
got: 4
1
got: 1
2
got: 2
Here are all of the 23 numbers you gave me:
5 6 7 8 1 3 5 6 7 1 2 3 4 5 6 67 8 1 2 3 4 1 2