动态数组和删除运算符的 boost::python 内存错误

Posted

技术标签:

【中文标题】动态数组和删除运算符的 boost::python 内存错误【英文标题】:boost::python memory error with dynamic array and delete operator 【发布时间】:2020-07-10 18:00:22 【问题描述】:

我有这段代码用于测试 C++ 代码与原始 python 代码的速度(我使用指针数组来确保数据位于单个连续块中,因为向量必须在它增长时进行复制,这需要 O(N) 时间):

void MyClass::test_packet()
    time_t t1;
    time(&t1);
    PacketInfo* packets;
    for(int i = 0; i < 336000; i++)
        for(int j = 0; j < 18; j++)
            int N = 18;
            // allocate memory for 18 objects in a continous block
            packets = new PacketInfo[N];
            // create the packetInfo objects
            packets[i] = PacketInfo(i, i);
            // free the 18 memory blocks
            delete[] packets;
        
    

    time_t t2;
    time(&t2);
    cout << "total time for 336000 * 18 packets : " << (t2 - t1) << "seconds" << endl;

BOOST_PYTHON_MODULE(MyClass)

    class_<MyClass>("MyClass", init< /*parameter types go here */>())
        // some other functions
        .def("test", &MyClass::test_packet);


python 测试文件如下所示:

from MyClass import *
MyClass.test()

这给了我一个双重空闲或损坏的内存错误:

*** Error in `python3': double free or corruption (!prev): 0x00000000016b1b10 ***

我评论了 delete[] 运算符,但这给了我一个分段错误:

Erreur de segmentation (core dumped)

知道如何解决这个问题吗?

谢谢

【问题讨论】:

【参考方案1】:

这里有一些不正确的代码

for(int i = 0; i < 336000; i++)
    for(int j = 0; j < 18; j++)
        int N = 18;
        // allocate memory for 18 objects in a continous block
        packets = new PacketInfo[N];
        // create the packetInfo objects
        packets[i] = PacketInfo(i, i);

如果 i 大于 18(显然会这样),那么 packets[i] 将是一个越界数组访问。

packets[j] 的替代方案没有多大意义,因为分配相对于循环的定位不正确(大概它应该在循环之前)。

另外你关于向量的说法是不正确的。

vector<PacketInfo> packets(18);

将分配一个大小为 18 的向量,其中包含 18 个连续元素,并且由于该向量没有增长,因此也不会重新分配。

查看代码中的 cmets 我认为您要编写的代码是

for(int i = 0; i < 336000; i++)
    int N = 18;
    // allocate memory for 18 objects in a continous block
    vector<PacketInfo> packets(N);
    for(int j = 0; j < N; j++)
        // create the packetInfo objects
        packets[i] = PacketInfo(i, i);
    

【讨论】:

所以这只是一个错字...谢谢!顺便说一句,对于向量,这 18 个对象是在堆栈上还是在堆上?如果我没记错的话,如果我希望对象在堆上,它需要是一个指针向量 向量在栈上,PacketInfo 对象在堆上。上面的代码是这样,指针向量可能是也可能不是(因为它取决于你如何初始化指针)。 和你的代码版本完全一样的情况,指针本身在栈上,但它指向的东西在堆上。 好吧,我想我得回去看看内存分配了……再次感谢! 任何时候你在函数中声明一个变量,这个变量就在堆栈上(静态变量是一个例外)。这适用于任何类型的变量,包括指针。与指针的区别在于它们也指向某物,而某物可能不在堆栈上。理解指针的关键是始终将指针和指针指向的内容分开。它们不是一回事。

以上是关于动态数组和删除运算符的 boost::python 内存错误的主要内容,如果未能解决你的问题,请参考以下文章

4-数组指针与字符串1.4-动态内存分配

用new运算符动态分配一个长度为n的整型数组

删除由 boost::python 暴露的 std::vector 中的一个指针

C++ Boost Python numpy 数组初始化

std::atomic 作为类成员:使用 boost/python.hpp 时使用已删除的函数错误

Boost.Python:匹配 C++ 模板类型的嵌套命名空间