如何删除在函数参数上声明的新指针?
How to delete new pointer that declared on function parameters?
我的 class 有一个成员函数,它把自己类型的指针作为参数。
当我这样做时:
Object* obj1 = new Object();
Object* obj2 = new Object();
obj1->add_child(obj2)
delete obj1;
delete obj2;
obj1 = NULL;
obj2 = NULL;
和运行valgrind
,报告说:
HEAP SUMMARY:
in use at exit: 72,704 bytes in 1 blocks
total heap usage: 6 allocs, 5 frees, 73,098 bytes allocated
LEAK SUMMARY:
definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 72,704 bytes in 1 blocks
suppressed: 0 bytes in 0 blocks
我看an answer说still reachable
很好,没有漏水。然后,当我尝试这个时:
Object* obj = new Object();
obj1->add_child(new Object());
delete obj;
obj = NULL;
valgrind
的报告说:
HEAP SUMMARY:
in use at exit: 72,877 bytes in 3 blocks
total heap usage: 6 allocs, 3 frees, 73,098 bytes allocated
LEAK SUMMARY:
definitely lost: 144 bytes in 1 blocks
indirectly lost: 29 bytes in 1 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 72,704 bytes in 1 blocks
suppressed: 0 bytes in 0 blocks
很明显,我没有删除作为参数传递的 new Object()
指针。那么,如何删除该指针?
详细更新
add_child(Object* obj)
的定义:
void add_child(Object* obj) {
container.add_child(obj);
}
container
是 Object
的成员,它是模板 class.
的一个实例
Container<Object> container;
Container
定义是:
template<class T>
class Container {
public:
void add_child(const std::string& key, T* child) {
childrens.insert(std::pair<std::string,T*>(key, child));
}
private:
std::multimap<std::string,T*> childrens;
}
那么,孩子们其实就是一个std::multimap
.
我希望这个问题不会太长。
函数调用完成后,您将不再拥有 new
创建的指针。如果你调用的函数没有删除指针,那么你有内存泄漏。
您需要就谁拥有 指针做出明确且一致的选择。如果您决定 add_child
取得所有权, 那么调用者应该期望他们不需要删除传入的指针。如果您决定 add_child
不取得所有权,然后调用者保留所有权并删除指针。
您可以让 Object
获得所有权,因此它的析构函数会删除所有已添加到它的子指针。那么你的第一个例子应该是
Object* obj1 = new Object();
Object* obj2 = new Object();
obj1->add_child(obj2);
delete obj1; // also deletes obj2 automatically
你的第二个:
Object* obj = new Object();
obj->add_child(new Object());
delete obj; // automatically deletes the unnamed pointer passed in on previous line
如果您不想 Object
获得所有权,那么您就有问题了,因为您无法在调用者的上下文中删除 new Object()
。
如果您使用智能指针,管理所有权就会变得容易得多。 add_child
可以接受一个 std::unique_ptr<Object>
参数。
auto obj1 = std::make_unique<Object>();
auto obj2 = std::make_unique<Object>();
obj1->add_child(std::move(obj2)); // obj1 takes ownership
// both pointers automatically deleted at scope exit
auto obj = std::make_unique<Object>();
obj->add_child(std::make_unique<Object>());
// both pointers automatically deleted at scope exit
关于您仍然可以访问的内存块的 valgrind 报告不是您的错 - 。
我是怎么想到这个的:
块大小非常大 (72704
) 并且与分配对象的大小不匹配,所以接下来我尝试将 72704
除以 144
和 29
看看是不是这些对象的数组。
但不是,因为既没有72704
,也没有72704-4
,也没有72704-8
(数组,数组+32位整数来存储大小,数组+64位存储大小的整数)不可整除。然后我用谷歌搜索“72,704 still reachable
”,它显示了提到的问题。
其他回答者关于使用智能指针(如 std::unique_ptr
和 std::shared_ptr
)的建议很合理,我也推荐使用它们。
我的 class 有一个成员函数,它把自己类型的指针作为参数。
当我这样做时:
Object* obj1 = new Object();
Object* obj2 = new Object();
obj1->add_child(obj2)
delete obj1;
delete obj2;
obj1 = NULL;
obj2 = NULL;
和运行valgrind
,报告说:
HEAP SUMMARY:
in use at exit: 72,704 bytes in 1 blocks
total heap usage: 6 allocs, 5 frees, 73,098 bytes allocated
LEAK SUMMARY:
definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 72,704 bytes in 1 blocks
suppressed: 0 bytes in 0 blocks
我看an answer说still reachable
很好,没有漏水。然后,当我尝试这个时:
Object* obj = new Object();
obj1->add_child(new Object());
delete obj;
obj = NULL;
valgrind
的报告说:
HEAP SUMMARY:
in use at exit: 72,877 bytes in 3 blocks
total heap usage: 6 allocs, 3 frees, 73,098 bytes allocated
LEAK SUMMARY:
definitely lost: 144 bytes in 1 blocks
indirectly lost: 29 bytes in 1 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 72,704 bytes in 1 blocks
suppressed: 0 bytes in 0 blocks
很明显,我没有删除作为参数传递的 new Object()
指针。那么,如何删除该指针?
详细更新
add_child(Object* obj)
的定义:
void add_child(Object* obj) {
container.add_child(obj);
}
container
是 Object
的成员,它是模板 class.
Container<Object> container;
Container
定义是:
template<class T>
class Container {
public:
void add_child(const std::string& key, T* child) {
childrens.insert(std::pair<std::string,T*>(key, child));
}
private:
std::multimap<std::string,T*> childrens;
}
那么,孩子们其实就是一个std::multimap
.
我希望这个问题不会太长。
函数调用完成后,您将不再拥有 new
创建的指针。如果你调用的函数没有删除指针,那么你有内存泄漏。
您需要就谁拥有 指针做出明确且一致的选择。如果您决定 add_child
取得所有权, 那么调用者应该期望他们不需要删除传入的指针。如果您决定 add_child
不取得所有权,然后调用者保留所有权并删除指针。
您可以让 Object
获得所有权,因此它的析构函数会删除所有已添加到它的子指针。那么你的第一个例子应该是
Object* obj1 = new Object();
Object* obj2 = new Object();
obj1->add_child(obj2);
delete obj1; // also deletes obj2 automatically
你的第二个:
Object* obj = new Object();
obj->add_child(new Object());
delete obj; // automatically deletes the unnamed pointer passed in on previous line
如果您不想 Object
获得所有权,那么您就有问题了,因为您无法在调用者的上下文中删除 new Object()
。
如果您使用智能指针,管理所有权就会变得容易得多。 add_child
可以接受一个 std::unique_ptr<Object>
参数。
auto obj1 = std::make_unique<Object>();
auto obj2 = std::make_unique<Object>();
obj1->add_child(std::move(obj2)); // obj1 takes ownership
// both pointers automatically deleted at scope exit
auto obj = std::make_unique<Object>();
obj->add_child(std::make_unique<Object>());
// both pointers automatically deleted at scope exit
关于您仍然可以访问的内存块的 valgrind 报告不是您的错 -
我是怎么想到这个的:
块大小非常大 (72704
) 并且与分配对象的大小不匹配,所以接下来我尝试将 72704
除以 144
和 29
看看是不是这些对象的数组。
但不是,因为既没有72704
,也没有72704-4
,也没有72704-8
(数组,数组+32位整数来存储大小,数组+64位存储大小的整数)不可整除。然后我用谷歌搜索“72,704 still reachable
”,它显示了提到的问题。
其他回答者关于使用智能指针(如 std::unique_ptr
和 std::shared_ptr
)的建议很合理,我也推荐使用它们。