如何调试单个cpp_编译器自带的调试神器sanitizers

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,编译得到的结果如下:

3f450ae3463a77fcf2eb2de066c6f466.png

编译器直接给出了产生了会产生悬垂指针的具体代码,根本就不需要等到运行时才会出错。对于害怕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,再运行,会清清楚楚地得到越界所在的代码行:

b81273a52fc031547081bfcb61cc62ce.png

既然知道了代码所在的行,解决起来就易如反掌了。

关于sanitizers就介绍到这里了,它有很多的功能,且用法简单,编译器集成无需额外安装,文档在这里:

google/sanitizers​github.com
b4704a2b6ca0becd87657a88af7e5b7c.png

C++还有其它的调试工具,我之前的其它文章也介绍过一种。至少了解一种工具,常用内存问题都不会被吓住,从此以后,学习和实用C++都会变得很顺滑。

windows+visual studio的用法可以参看这篇:AddressSanitizer for Windows: x64 and Debug Build Support | C++ Team Blog

欢迎关注我的个人公众号「树屋编程」

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值