1

我有一个函数,它接受一个文件,逐行读取它,将每一行放入 a*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回归前完美,后破碎?

4

3 回答 3

3
char *chWordList[intFileSize]

这个字符串数组是在堆栈上分配的,因为它被声明为getWordlistFromFile. 退出函数后,堆栈指针减少,数组不再有效。

您应该使用与单个字符串相同的方法:在堆上分配。

char **chWordList = malloc(intFileSize*sizeof(char*))

这样,数组将保留函数的范围,您将能够在调用函数后使用它。

于 2013-09-07T15:02:08.557 回答
1

因为您正在返回指向其生命周期已过期的对象的指针。特别是,chWordsList返回值内部指向一个对象,该对象的生命周期在函数返回时结束。当您取消引用该指针时,您会得到未定义的行为(UB);因此,任何结果都不足为奇。

您需要做的是malloc内存,chWordList而不是将其声明为本地数组:

char **chWordList = malloc(intFileSize * sizeof(char*))
于 2013-09-07T15:01:38.197 回答
0

改变

char *chWordList[intFileSize];

char **chWordList = malloc(sizeof(char *) * intFileSize);

即分配chwordList并设置在WordList.

您的代码返回chWordList分配在堆栈上的数组变量,因此一旦函数getWordlistFromFile()完成并返回到main().

于 2013-09-07T15:07:37.607 回答