ifstream не открывается в рекурсивных вызовах - PullRequest
0 голосов
/ 20 октября 2010

у нас возникает странная проблема при попытке разобрать входной файл. идея состоит в том, что этот файл может включать в себя другие файлы, которые также должны быть проанализированы. Мы делаем это рекурсивно в функции, определенной как

int parse_inp(const char* filename)

Основной файл не анализирует, но рекурсивные вызовы не могут открыть свои файловые потоки.

int parse_inp(const char* filename)
{
    char buffer[BUFFER_MAX+1];
    char* token;
    std::string tok;
    int keywordSection;
    bool end_of_file;
    int cardNum;

    ...

    int i;
    std::string tempop;
    double tempd1, tempd2;
    SetSegmentCard2 tempSetSegmentCard2;
    int offset;

    printf("%s\n", filename);
    std::ifstream inp;
    inp.clear();
    inp.open(filename, std::ios::in);
    if(!inp.good() || !inp.is_open())
    {
        char path1[256];
        getcwd(path1,256);
        printf("CWD: %s\n", path1);
        fflush(NULL);
        printf("Unable to open '%s'\n", filename);
        return 0;
    }
    std::set<std::string> unrecognized;
    std::string line;
    while(inp.good() && !inp.eof())
    {
        getline(inp, line);
        strcpy(buffer, line.c_str());

        if (isComments(buffer)) //skip the comments line
            continue;

        if (buffer[0]=='*') //this is a keyword line
        {
            token = strtok(buffer," \n");
            keywordSection = is_inp_keyw(token);

            if (keywordSection==0)
                unrecognized.insert(token);
            cardNum = 0;
            continue;
        }

        //a data line
        tempop="";
        char* found = NULL;
        char path_buffer[100] = "Dyna3DWriter\\";
        int pos = 0;
        switch(keywordSection)
        {
            case 0: //not recognized
                //end of last keyword, not recognizable word
                break;
            case 1: //KEYWORD
                //"KEYWORD didn't do anything
                break;
            case 2: //TITLE
                break;
            case 3: //INCLUDE
                token = strtok(buffer, "\n");
                inp.clear();
                parse_inp(token);
                break;
            ...
        }
    }
    if(inp.is_open())
    {
        inp.close();
        inp.clear();
    }
}

Рекурсивные файлы никогда не анализируются. Я много осматривался, и большинство проблем, казалось, были либо в том, что бит сбоя был установлен (поэтому мы часто называем inp.clear()), либо в том, что мы делаем неверное предположение о текущем рабочем каталоге.

Для проверки второй теории мы добавили:

if(!inp.good() || !inp.is_open())
{
    char path1[256];
    getcwd(path1,256);
    printf("CWD: %s\n", path1);
    fflush(NULL);
    printf("Unable to open '%s'\n", filename);
    return 0;
}

И наш рабочий каталог, и имя файла указаны правильно. Мы видим то же поведение при использовании fopen(filename, "r") --- вызов perror("fopen") приводит к:

fopen: no such file or directory

РЕДАКТИРОВАТЬ : заполнено больше кода

Ответы [ 2 ]

2 голосов
/ 21 октября 2010

Вы уверены, что имя файла не содержит мусора или плохих символов, которые могли бы привести к этой проблеме?Если ошибка - файл не найден, это означает, что имя файла каким-то образом неверно.

Может ли это произойти из-за неверного объявления buffer?Мы не видим его в вашем коде.

Другая возможность состоит в том, что вы снова используете strtok при инициализации перед открытием файла.Вы должны избегать использования strtok на основе глобального хранилища для рекурсивного метода, подобного этому.Вы должны использовать strtok_r вместо.

0 голосов
/ 21 октября 2010

Если ваша рекурсивная функция вызывается очень глубоко, вы можете легко перегрузить ограничение ОС на количество открытых файлов.

Раньше я запускал свой Gentoo Linux с лимитом количества файлов для каждого процесса, равным 250, за исключением программ, которым требовалось гораздо больше.

Windows имеет ограничения, которые варьируются в зависимости от того, сколько памяти доступно системе и сколько объектов уже создано в системе.

Умный способ сделать это - иметь две функции. Первая функция - это та, которую все остальные вызывают, и она выполняет настройку, включая открытие файла. Вторая функция - это рекурсивная функция, и она принимает только ссылку на объект std :: ifstream.

EDIT:

Я вижу, что я неправильно понял ваш вопрос, а вы не рекурсивно открываете тот же файл . Я все равно оставлю свой вышеупомянутый абзац.

...