【问题标题】:Why deleting a pointer to a vector of pointers causes the pointers to be not valid?为什么删除指向指针向量的指针会导致指针无效?
【发布时间】:2012-07-23 04:16:03
【问题描述】:

编辑:感谢您的回答!我用std::string 返回类型声明了tellSomething 方法,而它应该是void

我把自己绊倒并责怪可怜的无罪delete运营商:)!


让我们考虑一个指向动态分配的vector 的指针,其中包含指向动态分配对象的指针:

// Create the vector of pointers
std::vector<A *>* v = new std::vector<A *>;

// Create two objects
A *a1 = new A;
A *a2 = new A;

// Populate the vector
v->push_back(a1);
v->push_back(a2);

// Delete the vector
delete v;

// Try accessing one of the objects
a1->tellSomething();    --> // Segmentation fault

不出所料,如果我删除vector,则包含对象上的delete不会被调用(我还验证了上面代码中从未调用过A::~A()),但是,最后一条指令给出了分段故障。

我对@9​​87654331@ 的期望有两点:

  • 调用每个包含对象的析构函数
  • 容器被释放

但在这种情况下,包含的对象是指针,所以没有调用析构函数。

另外,a1 不是列表末尾的NULL

那么,为什么会出现分段错误?


此处的完整示例:http://ideone.com/r8YC0


注意:我通常不将原始指针与 STL 容器一起使用,请将此代码视为纯理论示例,以帮助我理解 delete v 指令的逻辑。

【问题讨论】:

  • 这是a1-&gt;tellSomething 在做什么吗?
  • 我相信 delete 关键字调用了向量的析构函数,这反过来又删除了你所有的指针
  • 这不应该发生。你怎么知道它不在 tellSomething() 方法中 - 你排除了这种可能性吗?
  • @SamIam,当 AFAIR 被破坏时,向量不会释放指针。您必须手动释放它们,这就是智能指针在那里工作良好的原因。

标签: c++ destructor delete-operator


【解决方案1】:

你得到的崩溃是完全无关的;你声明 tellSomething 返回一个 std::string,但你从来没有返回任何东西,所以你进入了未定义的行为领域;程序在释放向量后崩溃的事实完全是运气,即使在第一次调用 tellSomething 时它也可能崩溃。

Fixing that problem 使您的程序运行良好(尽管您正在泄漏a1a2)。

顺便说一句,这会教你打开所有警告:使用-Wall,该代码会给你一个关于这个潜在问题的明确警告:

matteo@teolapmint ~/cpp $ g++ -Wall testwarns.cpp 
testwarns.cpp: In member function ‘std::string A::tellSomething()’:
testwarns.cpp:12:5: warning: no return statement in function returning non-void [-Wreturn-type]

(仅作记录:我个人建议使用-Wall -Wextra -ansi -pedantic编译,通常一个警告可以为您节省大量调试时间。

【讨论】:

  • 我喜欢与 clang 一起使用的警告是 -Weverything -Werror,然后是一长串 -Wno-* 参数来禁用我不关心的警告,例如 -Wno-c++98-compat -Wno-c++98-compat-pedantic
【解决方案2】:

崩溃来自于尝试调用无效的 std::string 析构函数:

std::string tellSomething() {
    std::cout << "A!" << std::endl;
}

a1-&gt;tellSomething(); 的调用告诉运行时在作用域中期待一个自动存储std::string,然后它会尝试销毁它。但这是无效的。

从技术上讲,这是未定义的行为,因为您没有返回您承诺的内容。

【讨论】:

  • 自从我使用 c++:ing 以来已经有一段时间了,但是这段代码怎么能编译呢?我希望它在编译时失败..
  • 好的,纯粹的。自从我进入 gcc 以来,已经有更长的时间了。 +1 顺便说一句,很好的答案。
【解决方案3】:

删除向量不会删除向量元素。您遇到了一个完全不同的问题,它是由 tellSomething() 在指定返回字符串时未能返回值引起的。

http://ideone.com/Jo9zi

【讨论】:

    【解决方案4】:

    它崩溃是因为在方法 A::tellSomething 的链接代码中,您应该返回您没有执行的 std::string。与删除v无关

    【讨论】:

      【解决方案5】:

      您的 tellSomething 方法缺少返回值。

      向该方法添加return ""; 可以使您的代码运行良好,尽管存在内存泄漏。

      【讨论】:

        猜你喜欢
        • 2020-10-28
        • 2011-08-04
        • 2013-04-14
        • 2018-04-14
        • 2010-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多