-4

以下是一段代码,其中用户输入了未知数量的单词,直到'E'输入,程序应该停止并打印出所有输入的单词。但是,当运行此程序时会产生分段错误。我是否访问了一些我不应该拥有的内存?

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

#define CAPACITY 10
#define NUM_OF_WORDS 10
int main(void)
{
    int num_words = 10;
    char *word= malloc(CAPACITY*sizeof(char));
    char **w=(char **) malloc(num_words*sizeof(char));
    int i;
    for(i = 0 ; scanf("%s", word)==1; ++i)
    {
        if(*word == 'E') 
            break;
        if( i == num_words-1)
            w = (char **)realloc(w, (num_words *=2) * sizeof(char));
        w[i] =(char *) malloc(strlen(word)+1 * sizeof(char));
        strcpy(w[i], word);
    }
    int x = 0;
    for(x = 0 ; x<num_words ; x++)
        printf("%s", w[x]);
    return 0;
}
4

2 回答 2

1

您的初始分配代码如下:

char *word = malloc(CAPACITY*sizeof(char));
char **w = (char **) malloc(num_words*sizeof(char));

这两个都分配 10 字节的内存。你的第二个应该是:

char **w = (char **) malloc(num_words*sizeof(char *));

或者:

char **w = malloc(num_words*sizeof(*w));

它们都为 10 个指针分配了足够的内存(这可能是原始代码的八倍)。第二个可以说是更好的风格;第一个无疑是经典风格。在 C 中,malloc()不需要强制转换;在 C++ 中,它是。

这可能不是问题的全部;这几乎可以肯定是一个促成因素。

此外,您没有检查内存分配;这是不可取的。你应该经常检查它们。


这段代码:

if (i == num_words-1)
    w = (char **)realloc(w, (num_words *=2) * sizeof(char));

在两个帐户上玩火(加上先前诊断的问题的重复):

  1. 参数列表中的分配......通常不被认为是一个好主意。我不会用那个地方写代码,我会发回我被要求审查的包含它的代码。这在技术上并没有错。它会起作用的。但这并没有让后来的维护程序员的生活更轻松。

  2. 您永远不应该重新分配一个指针,例如w并将新空间分配给同一个指针。如果内存分配失败,您将返回一个空指针,因此您丢失了指向先前数据的唯一指针,该数据仍被分配。那是内存泄漏。此外,如果内存分配失败,您必须撤消参数列表中的分配,因为分配的空间仍然是原始大小。我认为你最好使用:

    if (i == num_words - 1)
    {
        size_t new_size = (num_words * 2);
        char **new_data = realloc(w, new_size * sizeof(*new_data));
        if (new_data == 0)
            ...handle error; w is still valid, and num_words is still correct too...
        num_words = new_size;
        w = new_data;
    }
    
于 2012-04-06T03:06:09.267 回答
0

您的变量num_words保存数组的当前最大大小w,但这与数组中实际的字数不同。

当您遍历w数组时,您正在遍历太多项目 - 其中的某些元素w没有有效的字符串 - 尝试打印它们会导致段错误。

于 2012-04-06T03:05:57.483 回答