load()
中计算大小。print()
在屏幕上打印字典。创建指向字符串的全局指针,在load()
中创建字符串数组,并将本地数组指定给全局指针。
如果我尝试在load()
内打印全局数组(以及本地数组),一切都很好,但是如果使用print()
进行打印,则会在数组末尾的某处发生段错误。 GDB和valgrind输出对我来说似乎很神秘。我放弃。怎么了?
来源和字典是here。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// length of the longest word in dictionary
#define LENGTH 45
// dictionary file
#define DICTIONARY "large"
// prototypes
void load(const char* dictionary);
void print(void);
// global dictionary size
int dict_size = 0;
// global dictionary
char **global_dict;
int main(void)
{
load(DICTIONARY);
print();
return 0;
}
/**
* Loads dictionary into memory.
*/
void load(const char* dictionary)
{
// open dictionary file
FILE *dict_file = fopen(dictionary, "r");
// compute size of dictionary
for (int c = fgetc(dict_file); c != EOF; c = fgetc(dict_file))
{
// look for '\n' (one '\n' means one word)
if (c == '\n')
{
dict_size++;
}
}
// return to beginning of file
fseek(dict_file, 0, SEEK_SET);
// local array
char *dict[dict_size];
// variables for reading
int word_length = 0;
int dict_index = 0;
char word[LENGTH + 1];
// iteration over characters
for (int c = fgetc(dict_file); c != EOF; c = fgetc(dict_file))
{
// allow only letters
if (c != '\n')
{
// append character to word
word[word_length] = c;
word_length++;
}
// if c = \n and some letters're already in the word
else if (word_length > 0)
{
// terminate current word
word[word_length] = '\0';
//write word to local dictionary
dict[dict_index] = malloc(word_length + 1);
strcpy(dict[dict_index], word);
dict_index++;
// prepare for next word
word_length = 0;
}
}
// make local dictioinary global
global_dict = dict;
}
/**
* Prints dictionary.
*/
void print(void)
{
for (int i = 0; i < dict_size; i++)
printf("%s %p\n", global_dict[i], global_dict[i]);
}
答案 0 :(得分:6)
答案很简单,您将指针指向load()
的本地变量,并在load()
返回时将其解除分配,因此它在{{1}中无效导致未定义的行为。
你甚至评论过它
print()
您有两种选择:
不要使用全局变量,与全局变量一起使用的模式没有任何好处,相反,它非常危险。您可以从函数// local array <-- this is your comment not mine
char *dict[dict_size];
返回动态分配的poitner,然后将其传递给load()
。
使用print()
分配指针数组。
malloc()
为什么我不喜欢全局变量?
但是,当然,当你获得经验时,你不会做这种事情,所以它更多是你的错,而不是全局变量,但看到仍在学习的程序员是很常见的,使用全局变量来解决函数之间共享数据的问题,这就是参数的用途。
所以使用全局变量+不知道如何正确处理它们是不好的,而是学习函数参数,你将解决所有需要全局变量通过程序中的不同函数传递数据而不使用全局变量的问题。
这是你自己的代码,我删除了global_dict = malloc(dict_size * sizeof(*global_dict));
变量,并在global_dict
中使用了动态内存分配,我也对load()
执行了一些错误检查,你应该改进那部分你希望代码是健壮的,其余的是自我解释
malloc()
答案 1 :(得分:1)
在LibGit2Sharp.0.21.0.176
中,您创建并填充局部变量NuGet
,然后只将指针load()
指定给该变量。但是只要char *dict[dict_size];
返回,就不能再访问任何局部变量了。
那个问题stealing the hotel keys,因为它在答案中得到了很好的解释
答案 2 :(得分:0)
问题在这里:
char *dict[dict_size];
通过这样的声明,数组的内存被自动分配(它只能在load()
中触及),在load()
之后调用dict
的内存可以访问覆盖。似乎覆盖发生在程序结束的某个地方(意外)。
char **dict = malloc((1 + dict_size) * sizeof(*dict));
因此,我为dict
动态分配内存(在程序结束或free(global_dict)
之前不可触及)
P.S。 我同意全局变量是危险的,但解决这种设计的问题是分配的约束。