简体   繁体   English

如何删除指针数组

[英]How to delete an array of pointers

I've been brushing up on my C++ as of late, and I have a quick question regarding the deletion of new'd memory. 我一直在刷我的C ++,我有一个关于删除新内存的快速问题。 As you can see below i have a simple class that holds a list of FileData *. 正如您在下面看到的,我有一个包含FileData *列表的简单类。 I created an array to hold the FileData objects to be pushed into the list. 我创建了一个数组来保存要推送到列表中的FileData对象。 When ReportData is destructed I loop through the list and delete each element. 当ReportData被破坏时,我遍历列表并删除每个元素。 My question is, how can i delete the array when I'm done using reportData, so that I do not have any memory leaks? 我的问题是,当我使用reportData时,如何删除数组,以便我没有任何内存泄漏?

Report.h 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 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'.


        }

--- I removed the delete oprations from the ReportData dtor and I'm now looping and deleting: ---我从ReportData dtor中删除了删除操作,现在我正在循环和删除:

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

This is easier to understand then having to rely on a separate object's dtor to clean up memory. 这更容易理解,然后必须依靠单独的对象的dtor来清理内存。

You don't. 你没有。 fileData is an automatic (stack) variable. fileData是一个自动(堆栈)变量。 You didn't allocate it with new, so you don't delete it. 您没有使用new分配它,因此不要删除它。

[Edit: also I'm not sure, but I think you could face problems deleting those FileData objects from main.cpp, considering that they were allocated in some dll. [编辑:我也不确定,但我认为你可能会遇到从main.cpp删除那些FileData对象的问题,考虑到它们是在某些dll中分配的。 Does the dll provide a deleter function?] dll是否提供了删除功能?]

Your array is not dynamically allocated, so you don't need to delete it. 您的数组未动态分配,因此您无需删除它。 Each element, however, is pointing to a dynamically allocated object (from your comment): 但是,每个元素都指向一个动态分配的对象(来自您的注释):

createfd is a function pointer that returns a new instance of FileData though createfd是一个函数指针,它返回FileData的新实例

What you need to do is loop over the elements of the array, and free each of them. 你需要做的是遍历数组的元素,并释放它们中的每一个。

for(int i = 0; i < num_files; i++)
{
    delete fileData[i];
}
// 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;

There is no need to delete or clear either of the two lists - this will be done for you by the default destructor. 无需删除或清除两个列表中的任何一个 - 默认析构函数将为您完成此操作。 Assuming that the pointers the lists contain (to "arrays"? I'm not clear) have been dynamically allocated, you need to delete them. 假设列表中包含的指针(到“数组”?我不清楚)已经动态分配,你需要删除它们。 However, you can (and should) avoid having to do this explicitly by making the lists contain std::vectors or suitable smart pointers. 但是,您可以(并且应该)通过使列表包含std :: vectors或合适的智能指针来避免必须明确地执行此操作。

"My question is, how can i delete the array when I'm done using reportData, so that I do not have any memory leaks?" “我的问题是,当我使用reportData时,如何删除数组,以便我没有任何内存泄漏?”

That's the wrong question. 这是错误的问题。 The right question is "who should delete these FileData objects?", and the answer is "whoever constructs them, ideally, in this cae Main.cpp". 正确的问题是“谁应该删除这些FileData对象?”,答案是“理想情况下,在这个cae Main.cpp中构建它们的人”。 Farming out the job to reportData is awkward and precarious; 通过报告数据来完成工作是尴尬和不稳定的; doing the job twice (once in the ReportData destructor and again in Main.cpp) violates memory. 两次执行该作业(一次在ReportData析构函数中,再次在Main.cpp中)违反内存。

If you must destroy the objects in ~ReportData(), just don't do anything about them in Main.cpp. 如果你必须销毁~ReportData()中的对象,只是不要在Main.cpp中对它们做任何事情。 Then your code will be correct. 那么你的代码就是正确的。 Horrible, but correct. 可怕,但是正确的。

Have you thought about wrapping FileData* with a smart pointer? 你有没有想过用智能指针包装FileData *?

The problem with your dtor is that an exception will cause a memory leak (with some other problems relating to exceptions leaking out of dtor's). 你的dtor的问题是异常会导致内存泄漏(还有一些与异常泄漏有关的其他问题)。

Don't deallocate anything in main(). 不要在main()中释放任何内容。

The destructor for reportData will handle everything allocated with createfd() (just make sure that createfd() is returning what it allocated with new(), since you must not delete anything that was not new'd). reportData的析构函数将处理用createfd()分配的所有内容(只需确保createfd()返回它使用new()分配的内容,因为你不能删除任何不是new'd的内容。

fileData is allocated locally, on the stack, not through new. fileData在堆栈上本地分配,而不是通过new分配。 Since it wasn't allocated by new, don't delete it. 由于它没有被新分配,所以不要删除它。

The pointers that were passed into fileData were also passed into reportData, and reportData is responsible for all deletions there. 传递给fileData的指针也传递给reportData,reportData负责那里的所有删除。 You could check to see that they weren't allocated from an inaccessible memory pool (say in a dynamically linked library); 您可以检查它们是否未从无法访问的内存池中分配(例如在动态链接的库中); if they were, that's a problem. 如果他们是,这是一个问题。

So, assuming the deletes are correct in the ReportData destructor, remove any deletion of fileData and you're good. 因此,假设ReportData析构函数中的删除是正确的,删除​​fileData的任何删除,你就是好的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM