malloc 到指针“数组”的元素

塔西奥·科斯塔

那里。

我正在尝试制作一个程序来读取 N 个单词(它在您键入 - 时结束)并排序打印。

我的问题是:我正在尝试使用某种动态的 char* 数组。它重新分配一个元素,但是当我尝试在堆上为字符串创建空间时崩溃(第 21 行)。

有没有可能修复?谢谢你。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define WORD_SIZE 11

int main()
{
        char word[WORD_SIZE];
        char **set;
        int j;
        int numberWord = 0;

        /* input */
        printf("Insert a word, or '-' to stop: ");
        fgets(word, WORD_SIZE, stdin);

        while (strcmp(word, "-\n")) {
                /* process */
                set = realloc(set, sizeof(char *) * (numberWord + 1));
                set[numberWord] = malloc(sizeof(char) * WORD_SIZE);
                numberWord++;

                /* input */
                printf("Insert a word, or '-' to stop: ");
                fgets(word, WORD_SIZE, stdin);
        }

        /* output */
        printf("\nSORTED:\n");
        for (j = 0; j <  numberWord; j++) {
                printf("%s", set[j]);
        }

        printf("\n");
        free(set);

        return 0;
}
大卫·C·兰金

除了初始化set和复制之外word,您还缺少许多其他一些微妙的问题,这些问题可能会困扰您。首先,让我们从几个无关紧要的逻辑问题开始。很少,如果你真的想存储一个'\n'末端悬空的字符串,只需删除newlineread 并包含在wordby 中fgets,例如

        /* remove trailing '\n' */
        size_t len = strlen (word);
        if (word[len - 1] == '\n')
            word[--len] = 0;            /* overwrite with nul-byte */

len还使您能够分配所需的确切内存量word,例如len + 1

这也使您有机会在此时通过简单的长度字符比较来检查退出条件,例如

         if (len == 1 && *word == '-')   /* test for '-' */
            break;

(这也意味着您的阅读循环可以简单地for (;;) {...}不存储"-"为您的单词之一)

正如我在评论中所指出的,永远不要直接分配被重新分配的指针的返回值。为什么?如果realloc失败,set则不会被释放并realloc返回NULL——然后您将其分配给set丢失对的引用set并造成内存泄漏。相反,始终使用临时指针,例如

        /* process - validate all allocations */
        void *tmp = realloc (set, sizeof *set * (numberWord + 1));
        if (!tmp) {
            fprintf (stderr, "error: virtual memory exhausted - realloc.\n");
            break;
        }
        set = tmp;

您正在为 each 分配内存word,但未能free为每个单词分配内存。如果此后不再需要内存,则可以在输出循环中执行此操作,例如

    /* output */
    printf ("\nSORTED:\n");
    for (j = 0; j <  numberWord; j++) {
        printf (" %s\n", set[j]);
        free (set[j]);          /* don't forget to free word */
    }
    free(set);                  /* free pointers */

    putchar ('\n');             /* don't use printf for single char */

上面你表示你正在按SORTED顺序输出你的单词,但你没有对你的单词进行排序。对单词进行排序的最简单方法是为 in 中的指针创建一个简单的比较函数set,然后传递setqsort进行排序,例如

int cmpstrings (const void *a, const void *b) {
    return strcmp (*(char * const *)a, *(char * const *)b);
}

int main (void) {
    ...
    qsort (set, numberWord, sizeof *set, cmpstrings);   /* sort */

将所有部分放在一起并以更简洁的方式重新排列您的输入请求的逻辑,您可以执行以下操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define WORD_SIZE 11

int cmpstrings (const void *a, const void *b) {
    return strcmp (*(char * const *)a, *(char * const *)b);
}

int main (void) {

    char word[WORD_SIZE] = "",
        **set = NULL;
    int j, numberWord = 0;

    for (;;) {

        /* input */
        printf("Insert a word, or '-' to stop: ");
        fgets(word, WORD_SIZE, stdin);

        /* remove trailing '\n' */
        size_t len = strlen (word);
        if (word[len - 1] == '\n')
            word[--len] = 0;            /* overwrite with nul-byte */

        if (len == 1 && *word == '-')   /* test for '-' */
            break;

        /* process - validate all allocations */
        void *tmp = realloc (set, sizeof *set * (numberWord + 1));
        if (!tmp) {
            fprintf (stderr, "error: virtual memory exhausted - realloc.\n");
            break;
        }
        set = tmp;

        set[numberWord] = malloc (sizeof *set[numberWord] * (len + 1));
        if (!set[numberWord]) {
            fprintf (stderr, "error: virtual memory exhausted - malloc.\n");
            break;
        }

        strcpy (set[numberWord], word);
        numberWord++;
    }

    qsort (set, numberWord, sizeof *set, cmpstrings);   /* sort */

    /* output */
    printf ("\nSORTED:\n");
    for (j = 0; j <  numberWord; j++) {
        printf (" %s\n", set[j]);
        free (set[j]);          /* don't forget to free word */
    }
    free(set);                  /* free pointers */

    putchar ('\n');             /* don't use printf for single char */

    return 0;
}

示例使用/输出

$ ./bin/dynwords
Insert a word, or '-' to stop: my
Insert a word, or '-' to stop: dog
Insert a word, or '-' to stop: has
Insert a word, or '-' to stop: fleas
Insert a word, or '-' to stop: the
Insert a word, or '-' to stop: cat
Insert a word, or '-' to stop: doesn't
Insert a word, or '-' to stop: have
Insert a word, or '-' to stop: any
Insert a word, or '-' to stop: -

SORTED:
 any
 cat
 doesn't
 dog
 fleas
 has
 have
 my
 the

在你写的,可动态分配内存的任何代码,你有2个职责关于分配的内存中的任何模块:(1)始终保持一个指针起始地址的内存,因此块,(2),可以释放时,它是没有不再需要。

您必须使用内存错误检查程序来确保您没有在分配的内存块之外/之外写入,尝试读取或基于未初始化值的条件跳转,并最终确认您已释放所有内存你已经分配了。

对于Linuxvalgrind是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序,例如

$ valgrind ./bin/dynwords
==10572== Memcheck, a memory error detector
==10572== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==10572== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==10572== Command: ./bin/dynwords
==10572==
Insert a word, or '-' to stop: my
Insert a word, or '-' to stop: dog
Insert a word, or '-' to stop: has
Insert a word, or '-' to stop: fleas
Insert a word, or '-' to stop: the
Insert a word, or '-' to stop: cat
Insert a word, or '-' to stop: doesn't
Insert a word, or '-' to stop: have
Insert a word, or '-' to stop: any
Insert a word, or '-' to stop: -

SORTED:
 any
 cat
 doesn't
 dog
 fleas
 has
 have
 my
 the

==10572==
==10572== HEAP SUMMARY:
==10572==     in use at exit: 0 bytes in 0 blocks
==10572==   total heap usage: 18 allocs, 18 frees, 402 bytes allocated
==10572==
==10572== All heap blocks were freed -- no leaks are possible
==10572==
==10572== For counts of detected and suppressed errors, rerun with: -v
==10572== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始终确认您拥有freed分配的所有内存并且没有错误。

仔细检查一下,如果您有任何问题,请告诉我。有许多细微的变化,所以如果有什么你不明白的地方,请在下面发表评论。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章