记一次虚函数使用的查错过程

起因

一个基础库中对资源回收的行为出现异常,经过排查,发现是基础库实现时对虚函数的调用出现问题造成的,记录下来吧。

纯虚函数的版本

#include 
using namespace std;

class B
{
	public:
		~B()
		{
			close();
		}

		void close()
		{
			doClose();
		}

		virtual void doClose() = 0;
};

class D : public B
{
	virtual void doClose()
	{
		cout <<"D::doClose()" <<endl;
	}
};

int main(int argc, char *argv[])
{
	B * p = new D();
	p->close();
	delete p;

	return 0;
}

# g++ main.cpp && ./a.out 
D::doClose()
pure virtual method called
terminate called without an active exception
Aborted

这里很好理解,D先于B析构,之后的doClose就没有对应的函数可用。

普通虚函数版本

#include 
using namespace std;

class B
{
	public:
		~B()
		{
			close();
		}

		void close()
		{
			doClose();
		}

		virtual void doClose()
		{
			cout <<"B::doClose()" <<endl;
		}
};

class D : public B
{
	virtual void doClose()
	{
		cout <<"D::doClose()" <<endl;
	}
};

int main(int argc, char *argv[])
{
	B * p = new D();
	p->close();
	delete p;

	return 0;
}

# g++ main.cpp && ./a.out 
D::doClose()
B::doClose()

道理也很好理解,D析构后,B析构时调用的doClose指向B::doClose的实现,出现问题的代码逻辑就是这种实现。

总结

库中这块代码逻辑的原意是希望在对象析构时释放占用的资源,当释放资源的操作是纯虚函数时,程序异常退出,问题提前出现。而当释放资源的操作是普通虚函数时,问题就被隐藏掉了,如果管理的资源不是非常敏感的资源,问题可能就会被带到上线后再出现,而且排错非常麻烦。
一切的一切还是要看基本功啊

你可能感兴趣的:(linux,开发)