简体   繁体   English

Visual Studio 2010 C ++运行时错误

[英]Visual Studio 2010 C++ runtime error

I came across strange behavior in Visual Studio 2010 C++ compiler. 我在Visual Studio 2010 C ++编译器中遇到了奇怪的行为。 Following code compiles but throws "Debug assertion failed" after execution with message: 以下代码编译但在执行消息后抛出“Debug assertion failed”:

"_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)" “_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)”

Compiles and runs smoothly under GCC. 在GCC下编译并顺利运行。 Is it my fault? 这是我的错吗?

#include <iostream>
#include <vector>


using namespace std;

typedef unsigned int uint;


class Foo {
    vector<int*> coll;
public:

    void add(int* item) {
       coll.push_back(item);
    }

    ~Foo() {
        for (uint i = 0; i < coll.size(); ++i) {
            delete coll[i];
            coll[i] = NULL;
        }
    }
};

int main()
{
   Foo foo;
   foo.add(new int(4));
   Foo bar = foo;

   return 0;
}

You didn't implement a copy constructor and copy assignment operator (see rule of three). 您没有实现复制构造函数和复制赋值运算符(请参阅规则3)。 This results in a shallow copy of the pointers in your vector, causing a double delete and the assertion. 这导致向量中的指针的浅拷贝,导致双重删除和断言。 EDIT: Double delete is undefined behavior so both VS and gcc are correct here, they're allowed to do whatever they want. 编辑:双删除是未定义的行为,因此VS和gcc在这里都是正确的,他们被允许做任何他们想做的事情。

Typically when you implement a destructor with non-trivial behavior you'll also need to write or disable copy construction and copy assignment. 通常,当您实现具有非平凡行为的析构函数时,您还需要编写或禁用复制构造和复制赋值。

However in your case do you really need to store the items by pointer? 但是在你的情况下,你真的需要通过指针存储项目吗? If not, just store them by value and that would fix the problem. 如果没有,只需按值存储它们即可解决问题。 Otherwise if you do need pointers use shared_ptr (from your compiler or boost) instead of raw pointers to save you from needing to write your own destructor/copy methods. 否则,如果您确实需要指针,请使用shared_ptr (来自您的编译器或boost)而不是原始指针,以免您需要编写自己的析构函数/复制方法。

EDIT: A further note about your interface: Interfaces like this that transfer ownership of passed in pointers can cause confusion by people using your class. 编辑:关于你的界面的另一个注意事项:这样的接口传递传入指针的所有权可能会导致使用你的类的人混淆。 If someone passed in the address of an int not allocated on the heap then your destructor will still fail. 如果有人传入了未在堆上分配的int的地址,那么析构函数仍然会失败。 Better is to either accept by value if possible, or clone the passed in item making your own call to new in the add function. 如果可能的话,最好是按值接受,或者克隆传入的项目,在add函数中自己调用new

You're deleting item twice, because the line 您要删除项目两次,因为该行

Foo bar = foo;

Invokes the default copy constructor, which duplicates the itempointer, rather than allocating and copying the data. 调用默认的复制构造函数,它复制itempointer,而不是分配和复制数据。

The problem is both the bar and foo member's vector element is same. 问题是barfoo成员的vector元素是相同的。 When foo goes out of scope it's destructor is called which deallocates the pointer leaving the bar vector element dangling. foo超出范围时,会调用析构函数来释放指针,使bar向量元素悬空。 bar destructor tries to deallocate it's vector element which was left dangling and is causing you the runtime error. bar析构函数尝试释放它的向量元素,它被悬空并导致运行时错误。 You should write a copy constructor. 你应该写一个拷贝构造函数。

Foo bar = foo; // Invokes default copy constructor.

Edit 1: Look at this thread to know about Rule of three 编辑1:看看这个帖子,了解三法则

The simpler solution here is not to use int* in the first place. 这里更简单的解决方案是首先不要使用int*

#include <iostream>
#include <vector>


using namespace std;

typedef unsigned int uint;


class Foo {
    vector<int> coll; // remove *
public:

    void add(int item) { // remove *
       coll.push_back(item);
    }

    // remove ~Foo
};

int main()
{
   Foo foo;
   foo.add(4); // remove `new` call
   Foo bar = foo;

   return 0;
}

In general, try to avoid new . 一般来说,尽量避免new

If you cannot, use a smart manager (like std::unique_ptr ) to handle the memory clean-up for you. 如果不能,请使用智能管理器(如std::unique_ptr )来为您处理内存清理。

In any case, if you're calling delete manually, you're doing it wrong . 在任何情况下,如果你手动调用delete你做错了 Note: not calling delete and letting the memory leak is wrong too 注意:不调用delete并让内存泄漏也是错误的

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

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