2012-07-24 102 views
3

编辑:谢谢你的回答!我宣布tellSomething方法的std::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 

正如预期的那样,如果我删除vector,对包含的对象的delete不叫(我也证实A::~A()从未在上面的代码中被调用),但是,最后的指令给出了分段错误。

我从delete v期望是两件事情:

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

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

此外,a1不是NULL在列表结束。

那么,为什么分段错误?


完整示例:http://ideone.com/r8YC0


注:我不经常使用与STL容器裸指针,请考虑下面的代码作为一个纯粹的理论例子来帮助我理解delete v指令的逻辑。

+0

它是什么'a1-> tellSomething'在做什么? – Wug 2012-07-24 19:15:26

+0

我相信'delete'关键字调用矢量的析构函数,它会依次删除所有指针 – 2012-07-24 19:15:32

+0

这不应该发生。你怎么知道它不在tellSomething()方法中 - 你排除了这种可能性吗? – mathematician1975 2012-07-24 19:16:26

回答

9

你得到的崩溃是完全不相关的;你宣称tellSomething返回std::string,但你永远不会返回任何东西,所以你进入未定义的行为 - 土地;该程序在释放该向量之后崩溃的事实纯属运气,即使在第一次调用tellSomething时也可能会崩溃。

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

顺便说一句,这教你打开了所有的警告:与-Wall代码就会给你这个潜在问题的一个明确的警告:

[email protected] ~/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进行编译,通常一个警告可以为你节省很多调试时间)。

+4

+1用于打开警告。 – 2012-07-24 19:19:53

+0

我喜欢用clang的警告是'-Weverything -Werror',然后是一长串'-Wno- *'参数来禁用我不在乎的警告,比如'-Wno-C++ 98-compat - WNO-C++ 98-COMPAT-pedantic'。 – bames53 2012-07-24 19:29:42

2

您的tellSomething方法缺少返回值。

将该return "";添加到该方法使您的代码运行得很好,尽管存在内存泄漏。

+0

可能是这个。 – Wug 2012-07-24 19:18:17

8

崩溃来自一个尝试呼叫无效std::string析构函数:

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

a1->tellSomething();的调用告诉运行时预计的范围,它然后试图破坏自动存储std::string。但这是无效的。

从技术上讲,这是未定义的行为,因为你没有返回你答应你会的东西。

+1

自从我是C++:ing以来,它已经有一段时间了,但是如何编译这些代码?我希望它在编译时失败.. – 2012-07-24 19:21:48

+1

@AvadaKedavra MSVS它确实失败。显然海湾合作委员会更宽松...... – 2012-07-24 19:23:41

+0

好吧,纯粹。自从我进入海湾合作委员会以来,它的时间更长了。 +1顺便说一句,很好的答案。 – 2012-07-24 19:24:38

3

删除矢量不会删除矢量元素。您遇到由tellSomething()在指定返回字符串时无法返回值的完全不同的问题。

http://ideone.com/Jo9zi

3

它崩溃,因为在法联代码A::tellSomething你应该返回std::string你不这样做。它与删除无关v