我有一个函数,它接受一个文件,逐行读取,将每一行放在*char[]
中,将这个二维数组放在一个结构中,然后返回这个结构:
wordlist.h:
#ifndef H_WORDLIST
#define H_WORDLIST
typedef struct {
char **chWordsList;
int listlen;
}Wordlist;
Wordlist getWordlistFromFile(char *chFilename);
char *getRandomWord();
#endif
该功能(加上标题):
#include "wordlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define WORDSIZE 100
Wordlist getWordlistFromFile(char *chFilename){
FILE *file = fopen(chFilename,"r");
if (file == NULL){
printf("Unable to open file %s. Check if the file exists and can be read by this user.\n",chFilename);
exit(1);
}
char chWord[WORDSIZE];
int intFileSize = 0;
//First: coundt the amount of lines in the file
while((fgets(chWord,WORDSIZE,file) != NULL)){
++intFileSize;
}
rewind(file);
char *chWordList[intFileSize];
for (int count = 0; (fgets(chWord,WORDSIZE,file) != NULL); ++count){
chWordList[count] = malloc( strlen(chWord +1));
strcpy(chWordList[count],chWord);
chWordList[count][strlen(chWord) -1] = 0;
}
fclose(file);
Wordlist wordlist;
wordlist.chWordsList = chWordList;
wordlist.listlen = intFileSize;
for (int i = 0; i < wordlist.listlen; ++i){
printf("%s\n", wordlist.chWordsList[i]);
}
return wordlist;
}
到目前为止,这很有效。最后一个for循环打印出给定文件的每一行,所有完全预期的行为都是完美的。现在,我实际上想要使用该功能。所以:在我的main.c:
Wordlist list = getWordlistFromFile(strFilePath);
for (int i = 0; i < list.listlen; ++i){
printf("%s\n", list.chWordsList[i]);
}
这给了我最奇怪的输出:
abacus
wordlist
(null)
(null)
��Ⳏ
E����H�E
gasses
虽然输出应为:
abacus
amused
amours
arabic
cocain
cursor
gasses
在我看来,几乎像一些指针得到free
d或其他东西,而其他指针保持不变。到底是怎么回事?为什么wordlist
在返回之前是完美的并且在之后被破坏了?
答案 0 :(得分:3)
char *chWordList[intFileSize]
这个字符串数组在堆栈上分配,因为它被声明为getWordlistFromFile
的本地。退出函数时,堆栈指针减少,数组不再有效。
您应该使用与单个字符串相同的方法:在堆上分配。
char **chWordList = malloc(intFileSize*sizeof(char*))
通过这种方式,数组将保持函数的范围,并且您可以在调用函数后使用它。
答案 1 :(得分:1)
因为您返回指向生命周期已过期的对象的指针。特别是,返回值内的chWordsList
指向一个对象,该对象的生命周期在函数返回时结束。当您取消引用该指针时,您将获得未定义的行为(UB);因此任何结果都不会令人感到意外。
您需要做的是malloc
的{{1}}内存,而不是将其声明为本地数组:
chWordList
答案 2 :(得分:0)
更改
char *chWordList[intFileSize];
到
char **chWordList = malloc(sizeof(char *) * intFileSize);
即分配chwordList
并在WordList
中设置。
您的代码返回在堆栈上分配的数组变量chWordList
,因此一旦函数getWordlistFromFile()
完成并返回main()
,它就无效。