Как удалить массив указателей - PullRequest
2 голосов
/ 23 июня 2009

В последнее время я освежил свой C ++, и у меня есть быстрый вопрос относительно удаления новой памяти. Как вы можете видеть ниже, у меня есть простой класс, который содержит список FileData *. Я создал массив для хранения объектов FileData, которые нужно вставить в список. Когда ReportData уничтожается, я перебираю список и удаляю каждый элемент. У меня вопрос, как я могу удалить массив, когда я закончу использовать reportData, чтобы у меня не было утечек памяти?

Report.h

class REPORTAPI ReportData {
public:

        ReportData()
        {
        }

        virtual ~ReportData()
        {
                printf("Starting ReportData Delete\n");
                for (list<FileData*>::iterator i = ReportFileData.begin(), e = ReportFileData.end(); i != e; )
                {
                    list<FileData*>::iterator tmp(i++);
                    delete *tmp;
                    ReportFileData.erase(tmp);
                }

                for (list<SupressionData*>::iterator i = ReportSupressionData.begin(), e = ReportSupressionData.end(); i != e; )
                {
                    list<SupressionData*>::iterator tmp(i++);
                    delete *tmp;
                    ReportSupressionData.erase(tmp);
                }

                ReportFileData.clear();
                ReportSupressionData.clear();

                printf("Finished ReportData Delete\n");
        }

        list<FileData *> ReportFileData;
        list<SupressionData *> ReportSupressionData;
}


extern "C" __declspec(dllexport) FileData* __stdcall createFileData(string fileName, long recordCount, long addPageCount)
{
        return new FileData(fileName, recordCount, addPageCount);
}

main.cpp

        ReportData *reportData = createrd();

        if (reportData != NULL)
        {
                CreateFileDataFunc createfd (reinterpret_cast<CreateFileDataFunc>(GetProcAddress (dll, "createFileData")));

                const int num_files = 5;
                FileData *fileData[num_files];

                char buff[256] = {'\0'};
                for (int i = 0; i < num_files; i++)
                {
                        sprintf(buff, "test: %d", i);
                        fileData[i] = createfd(buff, 1, 1);
                        reportData->ReportFileData.push_back(fileData[i]);
                }

                delete reportData;
                reportData = NULL;

                delete [] fileData; // this is throwing an access violation error:
                                    //EAccessViolation: 'Access violation at address 326025AF. Write of address 00000008'.


        }

--- Я удалил удаление операций из dtor ReportData и теперь я зацикливаюсь и удаляю:

            for(int i = 0; i < num_files; i++)
            {
                delete fileData[i];
            }

Это легче понять, чем полагаться на отдельный объектный dtor для очистки памяти.

Ответы [ 7 ]

6 голосов
/ 23 июня 2009

Ты не. fileData - это автоматическая (стековая) переменная. Вы не наделили его новым, поэтому не удаляете его.

[Edit: также я не уверен, но я думаю, что вы можете столкнуться с проблемами при удалении этих объектов FileData из main.cpp, учитывая, что они были размещены в некоторой DLL. Предоставляет ли dll функцию удаления?]

2 голосов
/ 23 июня 2009

Ваш массив не выделяется динамически, поэтому вам не нужно его удалять. Однако каждый элемент указывает на динамически размещаемый объект (из вашего комментария):

createfd - это указатель на функцию, который возвращает новый экземпляр FileData, хотя

Что вам нужно сделать, так это перебрать элементы массива и освободить каждый из них.

for(int i = 0; i < num_files; i++)
{
    delete fileData[i];
}
0 голосов
/ 23 июня 2009

Ничего не освобождайте в main ().

Деструктор для reportData будет обрабатывать все, что выделено с помощью createfd () (просто убедитесь, что createfd () возвращает то, что было выделено с помощью new (), так как вы не должны удалять все, что не было new'd).

fileData размещается локально, в стеке, а не через new. Поскольку он не был выделен новым, не удаляйте его.

Указатели, которые были переданы в fileData, также были переданы в reportData, и reportData отвечает за все удаления в нем. Вы можете проверить, что они не были выделены из пула недоступной памяти (скажем, в динамически связанной библиотеке); если бы они были, это проблема.

Итак, предполагая, что удаление корректно в деструкторе ReportData, удалите все удаления fileData, и все в порядке.

0 голосов
/ 23 июня 2009

Думали ли вы об обёртывании FileData * умным указателем?

Проблема с вашим dtor состоит в том, что исключение вызовет утечку памяти (с некоторыми другими проблемами, касающимися исключений, вытекающих из dtor).

0 голосов
/ 23 июня 2009

«У меня вопрос, как я могу удалить массив, когда я закончу использовать reportData, чтобы у меня не было утечек памяти?»

Это неправильный вопрос. Правильный вопрос - «кто должен удалять эти объекты FileData?», А ответ «кто создает их, в идеале, в этом файле Main.cpp». Разобраться в работе, чтобы сообщить: данные неловкие и ненадежные; выполнение работы дважды (один раз в деструкторе ReportData и снова в Main.cpp) нарушает память.

Если вы должны уничтожить объекты в ~ ReportData (), просто ничего не делайте с ними в Main.cpp. Тогда ваш код будет правильным. Ужасно, но правильно.

0 голосов
/ 23 июня 2009

Нет необходимости удалять или очищать любой из двух списков - это будет сделано для вас деструктором по умолчанию. Предполагая, что указатели, которые содержат списки (на «массивы»? Я не ясно), были распределены динамически, вам необходимо удалить их. Тем не менее, вы можете (и должны) избегать этого явно, создавая списки, содержащие std :: vectors или подходящие умные указатели.

0 голосов
/ 23 июня 2009
// allocate on the stack, no manual delete required
FileData *fileData[num_files];

// allocate on the heap, must delete after usage
FileData *fileData = new FileData[num_files];
// ..
delete [] fileData;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...