3

编辑:谢谢你的回答!我tellSomethingstd::string返回类型声明了该方法,而它应该是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

正如预期的那样,如果我删除vectordelete则不会调用包含的对象上的 (我还验证了A::~A()在上面的代码中从未调用过),但是,最后一条指令给出了分段错误。

我期望的delete v是两件事:

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

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

此外,a1不在NULL列表的末尾。

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


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


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

4

5 回答 5

9

你得到的崩溃是完全无关的;您声明tellSomething为返回 a std::string,但您从不返回任何内容,因此您进入未定义的行为领域;程序在释放向量后崩溃的事实是纯粹的运气,即使在第一次调用tellSomething.

解决这个问题可以让你的程序运行良好(尽管你正在泄漏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,通常一个警告可以为您节省大量调试时间)。

于 2012-07-24T19:16:59.997 回答
8

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

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

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

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

于 2012-07-24T19:16:46.440 回答
3

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

http://ideone.com/Jo9zi

于 2012-07-24T19:17:11.213 回答
3

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

于 2012-07-24T19:17:15.333 回答
2

您的tellSomething方法缺少返回值。

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

于 2012-07-24T19:16:23.837 回答