存档

‘C++编程’ 分类的存档

C++中的异常与栈展开

2014年2月16日 3 条评论

在《More Effective C++》一书中提到:
两种情况下destructor会被调用。第一种情况是当对象在正常状态下被销毁,也就是当它离开了它的生存空间(scope)或是被明确的删除;第二种情况是当对象被exception处理机制——也就是exception传播过程中的stack-unwinding(栈展开)机制——销毁。
那什么是栈展开(stack-unwinding)机制呢?在C++异常机制中,代码控制流会从throw语句跳转到第一个可以处理这种异常的catch语句的地方,在达到这[......]

继续阅读

MSVC CRT运行库启动代码分析

2013年9月14日 没有评论

在程序进入main/WinMain函数之前,需要先进行C运行库的初始化操作,通过在Visual Studio中调试,通过栈回溯可以找到位于crt0.c中的_tmainCRTStartup函数,这个函数负责进行一些初始化操作,_tmainCRTStartup的上一层调用来自kernel32.dll。这里简单分析一下crt0.c的代码。
实际上,C运行库代码又有两个版本,如果是静态编译的话代码位于crt0.c之中,如果是动态编译的话代码位于crtexe.c之中,这里可以通过项目属性的“配置属性”——[......]

继续阅读

error LNK2019 无法解析的外部符号

2013年4月20日 2 条评论

我是菜鸟我是菜鸟……最近遇到一个常识性错误,关于内联函数的(error LNK2019 无法解析的外部符号)。
通常编写函数时,会把声明放到头文件(*.h)中,而把函数定义放在源文件(*.cpp)中,在其他源文件中使用时包含对应的头文件即可。
但是内联函数(inline)不要定义在cpp文件中,因为我们通常都是包含头文件,而编译器在编译时会对内联函数进行展开操作,但是编译器只能在包含的头文件里搜索函数的定义体,如果头文件只有声明,显然编译器不知道该如何展开,于是就出错了。
每一个使用内联函数的地[......]

继续阅读

调试器也有MagicNumer——从一个奇葩的错误说起

2013年3月16日 17 条评论

最近太忙,博客也好久没有打理了,主要是没有东西可写,呵呵~
写代码的时候,在delete的时候遇到一个错误,提示“T.exe 中的 0x002a1614 处未处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突”,立刻就被其中的0xFEEEFEEE吸引住了,显然,这样的地址在用户空间(User Space)是不可能用到的,刚好前不久看到一条微博说调试器也有Magic Number,利用16进制构造出一些很有意思的数据,于是马上Google了一下0xFEEEFEEE[......]

继续阅读

const成员函数重载-error C2678 二进制< 没有找到接受const类型的左操作数的运算符

2013年3月5日 3 条评论

最近遇到的一个错误,重载类的小于比较操作符,然后通过algorithm中的sort对其进行排序时提示了一个编译错误:
1>—— 已启动生成: 项目: T, 配置: Debug Win32 ——
1>正在编译…
1>Main.cpp
1>e:\code\X\t\t\main.cpp(34) : warning C4996: ‘freopen’: This function or variable may be unsafe[......]

继续阅读

分类: C++编程 标签: ,

Boost编译与配置

2013年1月21日 6 条评论

老文章,在草稿箱存了一年多了)Boost是一个开源、可移植的强大的C++程序库,由C++标准委员会库工作组成员发起。官方网址为http://www.boost.org,SourceForge网址为http://sourceforge.net/projects/boost/。本文以Windows下Visual Studio为例讲解如何编译和配置Boost库。
首先从SourceForge上下载Boost库的压缩包,此时的最新版为1.47.0,下载地址为http://nchc.dl.sourcef[......]

继续阅读

分类: C++编程 标签: ,

Member Function Templates(成员函数模板)

2011年9月28日 2 条评论

Member Function Templates翻译成中文就是成员函数模板,这个东西我个人见得少,最初是在STL的auto_ptr源代码里面看到的,当时候也不是很明白;这几天又翻了翻《More Effective C++》,正好看到上面介绍的比较详细,就找了点资料总结一下。
为了更好的说明问题,我们自己定义一个Smart Pointer(智能指针,这里只是示例,所以定义是不完整和不完善的),假设现在我们手上有这样三个类:MusicProduct、CD、MP3,类之间的关系图如下:(Visual[......]

继续阅读

说一说string::size_type这个类型

2011年8月30日 3 条评论

其实以前我都不用这些XXX::size_type之类的类型的,一般都用int;后来看书看多了,就想还是用一下size_type;再后来,就发现问题了,于是我又用回了int来充当下标之类的类型。
问题是这样的,看看下面的代码有没有什么问题:

// 重点看for循环,里面的if可以忽略
int getValue(const string& str)
{
int res = 0, j = 0;
for (string::size_type i = str[......]

继续阅读

分类: C++编程 标签: ,

C++中的返回值优化(return value optimization)

2011年6月25日 3 条评论

返回值优化(Return Value Optimization,简称RVO),是这么一种优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用户返回,那么这个临时对象会消耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。而如果稍微做一点优化,就可以将成本降低到一个构造函数的代价,下面是在Visual Studio 2008的Debug模式下做的一个测试:(在GCC下测试的时候[......]

继续阅读

分类: C++编程 标签: ,

在构造函数抛出异常后析构函数将不再被调用

2011年5月29日 7 条评论

我发现要从构造函数中将错误信息传递给类的使用者有一个很简便的方法,那就是抛出异常,这样就可以直接传递字符串之类的信息了。如果是从一个普通的函数传回错误信息的话,以前往往选择返回一个错误代码,然后定义一个字符串二维数组,用相应的错误代号来取得错误信息。
但是如果构造函数要是抛出了异常,这个类的析构函数将不会被调用。如果不知道这一点,那么在构造函数中抛出异常就很危险了。析构函数不被调用,意味着清理工作不会被执行,会导致内存泄露、资源泄露等,这会给我们的产品带来很差的用户体验。
还是先来测试一下吧,证[......]

继续阅读