C++程序很容易出现越界、内存泄漏、内存重复释放、悬垂指针等问题,这些问题是新手的噩梦,可笑的是一般的C++教程从来不教如何解决这些问题,导致很多人自学者都是人肉解决,从此给心理蒙上了阴影。
其实针对C++有很多的工具可以用来定位这些问题,其中最垂手可得的是sanitizers,因为它已经被集成在编译器(gcc/clang/msvc)中,直接加上相关的编译选项就可以用,对于传说中恐怖的内存问题大都能手到擒来。
下面以mac下面的clang++为例。
先来看一个dangling pointer的例子:
//cat cat test.cc
#include <string>
#include <iostream>
int main(int argc, char **argv) {
auto f = []() {
std::string str = "1234567";
return &str; // 返回临时变量的地址,此处为悬垂指针
};
auto s = f();
std::cout<<*s<<"n";
}
来用clang++编译一下:clang++ -Wall -Werror -std=c++11 -fsanitize=undefined test.cc
,注意加上了-fsanitize=undefined
,编译得到的结果如下:
编译器直接给出了产生了会产生悬垂指针的具体代码,根本就不需要等到运行时才会出错。对于害怕C++ dangling pointer的人,这下放心了吧?
再来看一个下标越界的问题:
// cat memory-leak.cpp
#include <stdlib.h>
int main() {
int stack_array[100];
int index = 1001;
return stack_array[index]; // BOOM
}
上面的代码运行会崩溃。怎么办呢?加上sanitize重编:clang++ -O0 -g -fsanitize=address memory-leak.cpp
,再运行,会清清楚楚地得到越界所在的代码行:
既然知道了代码所在的行,解决起来就易如反掌了。
关于sanitizers就介绍到这里了,它有很多的功能,且用法简单,编译器集成无需额外安装,文档在这里:
google/sanitizersgithub.comC++还有其它的调试工具,我之前的其它文章也介绍过一种。至少了解一种工具,常用内存问题都不会被吓住,从此以后,学习和实用C++都会变得很顺滑。
windows+visual studio的用法可以参看这篇:AddressSanitizer for Windows: x64 and Debug Build Support | C++ Team Blog
欢迎关注我的个人公众号「树屋编程」