析构函数与运行错误

原创 2017年09月11日 16:11:34

  今天在做数据结构的实验课作业时,突然一直运行错误,可我检查了几次代码,也没有发现哪里有错(也并没有经常导致运行错误的,数组越界那些),经过20min左右的试探和摸索,终于发现了这次运行错误的时间,并且,还和析构函数有些关系

 

 (而且,最尴尬的是,在我发现以后,我才想起来,这个错误在我学C++的时候就犯过了,当时我还在自己的代码上注释过这个错误,强调以后要注意)…

 

然而到学数据结构时,居然印象已经不太深刻了…故写此博文,一方面,以后自己再犯这个错,可以快速找到;另一方面,如果有人不幸踩到这个坑,也许他们能从这篇中有一二启发。

 

  题目:





我最初的代码(DevC上正常运行,但在oj上报错):


#include <iostream>
#include <cstring>
using namespace std;
const int ok = 0;
const int error = -1;
const int maxn = 1e3 + 5;
int data[maxn];

class SeqList
{
private:
	int *list;
	int maxsize;
	int size;
public:
	SeqList()
	{
		maxsize = 1000;
		size = 0;
		list = new int[maxsize];
	}
	void init(int n)
	{
		size = n;
		for (int i = 0; i < n; i++) cin >> list[i];
	}
	~SeqList()
	{
		delete[]list;
	}
	void list_display()
	{
		cout << size << " ";
		for (int i = 0; i < size; i++) cout << list[i] << " ";
		cout << endl;
	}
	friend void MergeList(SeqList a, SeqList b, SeqList &c);
};

void MergeList(SeqList a, SeqList b, SeqList &c)
{
	int s_a = a.size, s_b = b.size, i, j, k;
	c.size = s_a + s_b;
	
	for (i = 0, j = 0, k = 0; i < s_a && j < s_b; )
	{
		if (a.list[i] < b.list[j]) c.list[k++] = a.list[i++];
		else c.list[k++] = b.list[j++];
	}
	
	while (i < s_a) c.list[k++] = a.list[i++];
	while (j < s_b) c.list[k++] = b.list[j++];
}

int main()
{
	SeqList temp1, temp2, ans;
	int size;
	cin >> size;
	temp1.init(size);
	cin >> size;
	temp2.init(size);

	MergeList(temp1, temp2, ans);
	ans.list_display();
	
	return 0;
}



报错信息:

/*
Runtime Error:[ERROR] A Not allowed system call: runid:143894 callid:146

*** glibc detected *** ./Main: double free or corruption (!prev): 0x084c1650 ***
Runtime Error:[ERROR] A Not allowed system call: runid:143894 callid:146

*** glibc detected *** ./Main: double free or corruption (!prev): 0x08b64650 ***
辅助解释:
A Not allowed system call: runid:143894 :使用了系统禁止的操作系统调用,看看是否越权访问了文件或进程等资源

*/


报错页面截图:


  百思不得其解,我就开始搜这些错误提示,然而搜了十几分钟,也一无所获,他们提到的数组越界等问题,我也没有,而对于ans列表,我也有给它的list数组动态分配足够大的空间。我仔仔细细检查了几次,还是觉得自己找不到错(此处对我当时的无知进行了美化,其实我当时是觉得,我应该没错吧,好像是oj错了)


  就在这时,突然想到了上学期学C++的类时,经常容易在析构函数上犯错,于是屏蔽了析构函数,提交一次





  发现屏蔽析构函数以后,居然就没有运行错了,可谓是又惊又喜....

  接下来我仔细想了想,这两种到底有什么区别,为什么没有析构就能通过,这时我突然想起


  因为我在 MergeList中,传入的参数 a 和 b 都是按照值传递的方式传递的,既然为值传递,作为临时变量,传参时会自动调用构造函数,返回时,会自动调用参数的析构函数...(而析构函数,本来是不会清楚动态分配的空间的,但既然我重写了析构,那new出来的数组空间,肯定都被析构掉了)


  可是,有一个很严重的问题是,a 和 b 作为参数传入时,它们的list数组,和主函数中的 temp1 和 temp2 的list数组,是共享空间的。而主函数与逆行完以后,temp1 和 temp2 必定也会调用析构函数,就相当于把同一个空间,析构了两次,自然会有运行错误


  那么,有没有什么方法能避免这个错误呢?

  

  当然是有的~

  1.  首先,如果不写析构函数就行,就如我的上一张截图,不自己写,默认的析构函数,是不会析构动态分配的空间的,虽然这种做法,毕竟还是不合适,但它确实可以避免许多问题


  (BTW,在这里说一下,重写析构函数以后,真的需要万事小心,我现在突然想起来,当初学C++的类时,几乎所有的错误,都是出现在析构函数上的,每次一屏蔽它就没事,不然就一直有错误抓狂



  2.  更加推荐的处理方法时,将 a 和 b 用引用的方式传递为参数,这样a和b就不是临时对象,函数也就不会在返回时,自动调用它们的析构函数了,就像这样



  const只是避免自己不小心改了不该改的a和b,不加也行,关键是一定要加上引用

  而且这个方法还有一个除了避免出错之外的好处,就是...运行速度更快了,从8变成了0偷笑


  从这个故事中,得到了一个教训:

  经常踩的坑,也还是应该好好记录整理下来。想当初,踩了那么多次析构函数的坑,出了那么多次运行错误,我以为印象深刻到,随时都能想起来的地步了。然而,今天还是找了很久才发现


  因此,特开博客的“经验教训”分类,以记下我在编程上遇到的,比较特别,或者比较值得记录下来的错误,并记下自己当时是怎么解决的。


版权声明:欢迎大家转载,转载请注明出处: ( http://blog.csdn.net/mofushaohua_ln )

析构函数什么时候调用

在这个对象的作用域最后.. 比如你在main里面声明了一个类A..那么~A()会在main结束时调用.. 如果在自定义的函数f()里面声明了一个A 函数f结束的时候就会调用~A() 或者你del...
  • williamzhang1111
  • williamzhang1111
  • 2015年06月19日 14:14
  • 321

C++ 析构函数

C++ 析构函数我使用的继承开发环境: Visual Studio 2010设计一个类时,如何写析构函数? 析构函数如果我们不写的话,C++ 会帮我们自动的合成一个,就是说:C++ 会自动的帮我们...
  • github_35160620
  • github_35160620
  • 2016年09月21日 00:02
  • 31588

C++构造函数与析构函数的解析

创建一个对象时,常常需要作某些初始化的工作,例如对数据成员赋初值。 注意,类的数据成员是不能在声明类时初始化的。如果一个类中所有的成员都是公用的,则可以在定义对象时对数据成员进行初始化。如: ...
  • u011392772
  • u011392772
  • 2015年01月16日 09:20
  • 7573

析构函数与构造函数的区别联系

在备战C++的学习当中,由于很多都用到函数,再次要求自己加深对函数的理解,C++中知识是并不多,我们只有不断的理解函数的真正用法,下面学习才会顺水推舟!加油!    析构函数(destructor)...
  • lishehe
  • lishehe
  • 2012年08月30日 15:22
  • 4077

C++ 构造函数和析构函数

这段时间学习了C++的一些知识,和其他编程语言一样,C++同样包括一些基础的知识,不同的是C++中出现了构造函数和析构函数,不论是构造函数还是析构函数,从字面意义上来理解都是函数,所以不要被它吓到哦O...
  • u010508826
  • u010508826
  • 2014年03月27日 19:40
  • 1770

析构函数与运行错误

今天在做数据结构的实验课作业时,突然一直运行错误,可我检查了几次代码,也没有发现哪里有错(也并没有经常导致运行错误的,数组越界那些),经过20min左右的试探和摸索,终于发现了这次运行错误的时间,并且...
  • mofushaohua_ln
  • mofushaohua_ln
  • 2017年09月11日 16:11
  • 338

c++构造函数和析构函数的区别?

构造函数: 什么是构造函数?通俗的讲,在类中,函数名和类名相同的函数称为构造函数。它的作用是在建立一个对象时,作某些初始化的工作(例如对数据赋予初值)。C++允许同名函数,也就允许在一个类中有多个构...
  • xinsong520
  • xinsong520
  • 2016年08月25日 18:35
  • 553

C++类的构造函数与析构函数

C++中每个类都有其构造与析构函数,它们负责对象的创建和对象的清理和回收,即使我们不写这两个,编译器也会默认为我们提供这些构造函数。下面仍然是通过反汇编的方式来说明C++中构造和析构函数是如何工作的。...
  • lanuage
  • lanuage
  • 2016年06月29日 22:11
  • 3116

浅谈C++析构函数

C++析构前言                                                                                             ...
  • kaisuihu
  • kaisuihu
  • 2013年03月28日 14:43
  • 655

析构函数声明为虚函数

Base *pb; inherit c;//inherit 是继承 Base的 pb=&c; delete   pb;时需要调用对象的析构函数,如果基类析构不是virtual型,会根...
  • b02330224
  • b02330224
  • 2014年04月02日 15:40
  • 731
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:析构函数与运行错误
举报原因:
原因补充:

(最多只允许输入30个字)