该程序旨在接收"n"个学生及其姓名并对它们进行排序(还没有到排序部分)。我无法弄清楚为什么我的程序在测试时崩溃。这是代码:
#include<stdio.h>
#include <stdlib.h>
#define MaxNameLen 100
int main() {
int n;
scanf("%d", &n);
char *names;
char **pointerToNames = (char **) malloc(n * sizeof(char));
if (pointerToNames == NULL)
return 0;
int i;
for (i = 0; i <= n; i++) {
names = (char *) malloc(MaxNameLen);
gets(names);
pointerToNames[i] = names;
}
for (i = 0; i < n; i++) {
free(pointerToNames[i]);
free(names);
}
}
你有三个问题。首先是你没有为"数组"分配足够的条目:
malloc(n * sizeof(char))
应该是
malloc(n * sizeof(char*))
第二个问题是读取循环:
for (i = 0; i <= n; i++) {
在这里,循环条件将导致您循环一次到多次,导致您写入超出分配的内容(如果您解决了第一个问题)。循环中的条件应与下一个循环中的条件i < n
。
第三个问题是你在循环中重复释放最后一个字符串
for (i = 0; i < n; i++) {
free(pointerToNames[i]);
free(names);
}
当您在上面的循环中将names
分配给pointerToNames[i]
时,当该循环完成后,names
将指向您读取的最后一个字符串,因此names
和pointerToNames[n - 1]
将指向同一字符串。
另外两个问题包括您没有释放首次分配的实际pointerToNames
内存。并且您不应该使用gets
(它早已被弃用,甚至在最新标准中删除)。请改用fgets
(或gets_s
)。
另外,不要投掷malloc
的回归。
您的第一个malloc
旨在为指向字符的指针分配内存N
但您正在分配N
个字符,这可能要少得多的内存。
更改此行:
char **pointerToNames = (char **) malloc(n * sizeof(char));
对此:
char **pointerToNames = malloc(n * sizeof(*pointerToNames));
此外:
for (i = 0; i < n; i++) {
free(pointerToNames[i]);
free(names);
这会为指示的索引释放内存,但您也会释放names
,这恰好是您用于分配内存的临时指针,然后您为每个 eement 分配了当前值 name
。因此,无需免费names
.
也许您发现将第二部分(为数组的每个元素分配内存的代码)更改为以下内容更简单:
for (i = 0; i < n; i++) {
pointerToNames[i] = malloc(MaxNameLen);
if (pointerToNames[i])
fgets(pointerToNames[i], MaxNameLen-1, stdin);
}
所以names
不再使用,而不是gets()
,使用 fgets()
.请注意,for
循环从0
到N-1
,而不是N
。 pointerToNames[N]
不是有效的数组元素。