创建 20k 阵列时bad_alloc

bad_alloc when creating 20k array

本文关键字:alloc bad 20k 阵列 创建      更新时间:2023-10-16

我必须做某种项目,但我被卡住了。我收到一个bad_alloc错误。我检查了很多次代码,试图谷歌一些解决方案,但仍然一无所获,这就是我在这里写的原因。问题是程序运行正常,但在任务管理器中,他的内存使用量增加到 2GB(据我所知,这是限制),然后它崩溃了。程序需要检查分配空间和复制变量的时间。这是代码的一部分:

class Table
{
    int *tablica;
    int size;
public:
Table()
    {
        tablica = NULL;
        size = 0;
    }
~Table()
    {
        delete tablica;
        size = 0;
    }
int *push_back(int val)
    {
        int *temp = new int[size];
        if(size % 10 == 0)
        {
            for(int i = 0; i < size; i++)
                temp[i] = tablica[i];
            tablica = new int[size + 10];
            for(int i = 0; i < size; i++)
                tablica[i] = temp[i];
        }
        tablica[size] = val;
        size++;
        delete []temp;
        return tablica;
    }
void test()
    {
            LONGLONG measure[100][6];
        LARGE_INTEGER performanceCountStart, performanceCountEnd;
        int cpy_tab [20000];
        for(int j = 0; j < 100; j++)
        {   
            for(int i = 0; i < 20000; i++)
                cpy_tab[i] = rand() % 10000 - 10000;
            performanceCountStart = startTimer(); 
            for(int i = 0; i < 500; i++)
                {
                    push_back(cpy_tab[i]);
                }
            performanceCountEnd = endTimer();
    measure[j][0] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][0]<<endl;
            delete []tablica;
            size = 0;
            performanceCountStart = startTimer(); 
            for(int i = 0; i < 2000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][1] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][1]<<endl;
            delete []tablica;
            size = 0;

            performanceCountStart = startTimer(); 
            for(int i = 0; i < 4000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][2] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][2]<<endl;
            delete []tablica;
            size = 0;

            performanceCountStart = startTimer(); 
            for(int i = 0; i < 8000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][3] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][3]<<endl;
            delete []tablica;
            size = 0;

            performanceCountStart = startTimer(); 
            for(int i = 0; i < 14000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][4] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][4]<<endl;
            delete []tablica;
            size = 0;
            performanceCountStart = startTimer(); 
            for(int i = 0; i < 20000; i++)
            {
                push_back(cpy_tab[i]);
            }
            performanceCountEnd = endTimer();
    measure[j][5] = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
            cout<<j<<"."<<measure[j][5]<<endl;
            delete []tablica;
            size = 0;
        }
    }

解决这个问题的任何想法对我来说都是值得的!

这样做时,您肯定会泄漏,并且可能会碎片化内存:

    int *temp = new int[size];
    if(size % 10 == 0)
    {
        for(int i = 0; i < size; i++)
            temp[i] = tablica[i];
        // Should free tablica here 
        tablica = new int[size + 10];
        for(int i = 0; i < size; i++)
            tablica[i] = temp[i];
    }

首先,分配一个size元素的 temp(即使不需要),然后分配一个 size+10 元素数组,该数组不会被释放。

我建议您使用第二个变量来记录容量,并在每次达到容量时将容量加倍。这样,您就不需要 2000 次分配来将数组增加到 20000 个元素,而是需要 15 次重新分配(和副本)。

你没有确切地显示你如何使用Table类,但你可能正在破坏堆。

test()函数将数据反复推送到tablica然后执行delete [] tablica,然后再进行另一轮推送。

但是,当 test() 函数最后一次删除tablica时,它不会将 poitner 设置为 NULL ,并且Table desctuctor 如下所示:

~Table()
{
    delete tablica;
    size = 0;
}

因此,它将继续并再次删除该指针,从而导致堆损坏。 请注意,~Table()中的delete操作应该是delete [] tablica;

另外,请注意,跨push_back()test() 和 dtor 函数管理tablica指针会导致情况混乱。

因为您正在泄漏 tablica 内存。以前

tablica = new int[size + 10];

添加一行

delete []temp;

一切都会好起来的。

更重要的是,在每次调用push_back中,您都在不必要地在临时中分配内存并将其删除。而是分配内存并在 if 条件内释放。