以下是一段代码,用户输入未知数量的单词,直到输入'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;
}
答案 0 :(得分: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个指针分配了足够的内存(可能是原始代码的8倍)。第二种可以说是更好的风格;第一个是无可挑剔的经典风格。在C中,malloc()
上的强制转换不是必需的;在C ++中,它是。
这可能不是整个问题;这几乎肯定是一个促成因素。
另外,您没有检查内存分配;这是不可取的。你应该经常检查它们。
此代码:
if (i == num_words-1)
w = (char **)realloc(w, (num_words *=2) * sizeof(char));
正在玩两个帐户(再加上先前诊断出的问题的重复):
参数列表中的赋值是...通常不被认为是个好主意。我不会编写具有该代码的代码,并且我会发回代码,我被要求审查包含它的代码。这在技术上不是错误的;它会工作。但它并没有让追求维护程序员的生活更轻松。
您永远不应重新分配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;
}
答案 1 :(得分:0)
您的变量num_words
保存w
数组的当前最大大小,但这与数组中实际的单词数不同。
循环遍历w
数组时,循环过多的项目 - w
的某些元素中没有有效的字符串 - 尝试打印它们会导致段错误。 / p>