第一次使用Malloc,程序崩溃

时间:2014-01-11 11:53:11

标签: c malloc

该计划旨在接收'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);
    }
}

2 个答案:

答案 0 :(得分:5)

你有三个问题。第一个是你没有为“数组”分配足够的条目:

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和{{ 1}}将指向相同的字符串。


另外两个问题包括你没有释放你最初分配的实际pointerToNames[n - 1]内存。并且您不应该使用pointerToNames(它已经被弃用,甚至在最新标准中被删除)。请改用fgets(或gets_s)。

另外,don't cast the return of malloc

答案 1 :(得分:1)

你的第一个malloc意味着为chars的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,而不是NpointerToNames[N]不是有效的数组元素。