C ++ управляет памятью в стеке (связанные списки) - PullRequest
2 голосов
/ 17 июня 2011

Извините, что опубликовал код спагетти, но я не знаю, откуда исходит ошибка.Предполагается, что эта функция имитирует упрощенную версию аспекта включения файлов в c ++.Он копирует, вставляет содержимое всех файлов с #include (и рекурсивно на содержимое включенного файла).

Чтобы не допустить рекурсивного включения двух файлов, я создал связанный список, в котором хранятся все ранее включенные файлы.Файлы, включенные впоследствии, будут проверены по этому связанному списку, чтобы убедиться, что файл не содержит предыдущий файл.Нам не разрешено динамически выделять, поэтому мы должны использовать память из стека для связанного списка.Я слышал, что это может вызвать проблемы с памятью в связанном списке, когда переменные выходят из области видимости.

Проблема в том, что части моего связанного списка перезаписываются случайными вещами.Если вы заметите операторы cout, результатом может быть что-то вроде этого

Предыдущий файл flist: input.txt

имя файла newnode: file1.txt

новый файл flist: file1.txt

Предыдущий флист: ВСЕ, ЧТО НЕ ДЕЛАЕТСЯ (странно, оно приняло значение строкового имени файла)

имя нового файла: file2.txt

new flist: file2.txt

Предыдущий flist: file2.txt (работает по назначению)

имя нового файла: file3.txt

new flist: file3.txt

Предыдущий flist: случайные символы (да? это из случайной памяти в стеке?)

имя нового файла: file4.txt

новый файл: file4.txt

Предыдущий файл: file4.txt (работает какпредназначен)

имя нового файла: file5.txt

новый список файлов: file5.txt

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

using namespace std;

struct Node { 
    string fileName;
    Node *link;
};

string extractfilename (string str) 
{
    string filename;

    if ((str.substr(10,1)) == "/" )
    {
        filename = str.substr((str.find_last_of("/"))+1,(str.length()) - (str.find_last_of("/"))-2);
        return filename;            
    } // if     
    else if ( (str.find_last_of("/")) != -1)
    {
        filename = str.substr((str.find_last_of("/")) + 1, (str.length()) - (str.find_last_of("/")) - 2);   
        return filename;
    } // else if 
    else
    {
        filename = str.substr(10,(str.length())-11);
        return filename;
    } // else

    return "ERROR";
}

void check_overlap (string filename, Node *flist)
{  
    while (flist != NULL)
    {
        if (flist->fileName == filename)
        {
            cerr << "Recursive include is being attempted. Terminating program." << endl;
            exit ( -1 );
        }
        flist = flist->link;
    }
}

void processOneFile( istream &in, ostream &out, Node *flist, string prefixDir )
{
    string str;
    getline(in,str);

    while(!(in.fail()))
    {
        string checkinclude = "";
        string checkabsolute = "";
        string prefix = "";
        string filename = "WHATEVER DOESNT MATTER";    
        string relpath = "";

        int checkrelative = 0;    
        int lastof = 0;    
        int length = str.length();

        if ( length > 11)
        {    
            checkinclude = str.substr(0,8);
            checkabsolute = str.substr(10,1);
            checkrelative = str.find_last_of("/");
        }    

        if (checkinclude == "#include")
        {
            ifstream newinput;
            filename = extractfilename(str);

            // PROBLEM WITH THIS ************
            //check_overlap(filename,flist) CAUSES INFINITE LOOP DUE TO DANGLING POINTERS?      
            Node newnode;

            cout << "Previous flist:    "<< flist->fileName << endl;

            newnode.fileName = filename;
            newnode.link = flist;
            Node surrogate_flist = newnode;

            cout << "newnode filename: "<< newnode.fileName << endl;       
            cout << "New flist:         "<< surrogate_flist.fileName << endl;
            cout << endl;
            // PROBLEM WITH THIS **************

            if (checkabsolute == "/" )
            {
                lastof = str.find_last_of("/");
                prefix = str.substr(10,lastof - 9);                    
                newinput.open((prefix + filename).c_str());

                if (!(newinput.is_open()))
                {
                    cout << prefix+filename << " cannot be opened" << endl;
                    exit( -1) ;
                }

                processOneFile(newinput,out,&surrogate_flist,prefix);
                newinput.close();
            } // if        
            else if ( checkrelative != -1)
            {
                relpath = str.substr(10, checkrelative - 9);        
                newinput.open((prefixDir+relpath+filename).c_str());

                if (!(newinput.is_open()))
                {
                    cout << prefixDir + relpath + filename << " cannot be opened" << endl;
                    exit( -1) ;
                }

                processOneFile(newinput,out,&surrogate_flist,(prefixDir+relpath));
                newinput.close();
            } // else if
            else
            {
                newinput.open((prefixDir + filename).c_str());

                if (!(newinput.is_open()))
                {
                    cout << prefixDir +filename << " cannot be opened" << endl;
                    exit( -1) ;
                }

                processOneFile(newinput,out,&surrogate_flist,prefixDir);
                newinput.close();
            } // else
        } // if
        else
        {
            out << str << endl;
        } // else
        getline(in,str);
    } // while
} // processOneFile

Спасибо

РЕДАКТИРОВАТЬ: Использование структуры узла исвязанные списки - это требование

Impразрешено динамическое выделение из строковых функций

добавлен основной и «полный» скомпилированный код

1 Ответ

2 голосов
/ 17 июня 2011

Учитывая требование использовать связанный список, вы должны использовать рекурсию. Это было бы что-то вроде этого:

struct Node
{
    string value;
    Node *link;
};

void Process(Node *front)
{
    Node newNode;
    newNode.link = front;
    if( /* some condition */ )
        return; // end recursion
    else
        Process(&newNode);
}

Первый вызов Process будет просто Process(NULL);, чтобы указать пустой список. Конечно, добавьте дополнительные параметры, чтобы включить остальную часть вашего состояния (я не здесь, чтобы делать вашу домашнюю работу для вас ;)).

Важно то, что вы не не модифицируете front->link, потому что ваш новый узел не будет действительным после возврата из функции и, следовательно, не должен становиться видимым для вызывающей стороны. Таким образом, вы должны построить этот список в обратном порядке (каждый рекурсивный вызов добавляет узел вперед).

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

...