看似自动指针释放

时间:2013-09-07 14:58:37

标签: c pointers

我有一个函数,它接受一个文件,逐行读取,将每一行放在*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在返回之前是完美的并且在之后被破坏了?

3 个答案:

答案 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(),它就无效。