加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

嵌入式開(kāi)發(fā)調(diào)試?yán)?| Sanitizer檢測(cè)器

04/07 15:38
2860
閱讀需 14 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

大家好,我是雜燴君。本次我們來(lái)分享一個(gè)開(kāi)發(fā)調(diào)試?yán)鳌猄anitizer。

Sanitizer簡(jiǎn)介

Sanitizer是由Google發(fā)起的開(kāi)源工具集,用于檢測(cè)內(nèi)存泄露等問(wèn)題。

鏈接:https://github.com/google/sanitizers/wiki/

它包括了AddressSanitizer、MemorySanitizer、ThreadSanitizer、LeakSanitizer等多種工具。這些工具最初是LLVM項(xiàng)目的一部分,后來(lái)也被GNU的GCC編譯器支持。從GCC的4.8版本開(kāi)始,就已經(jīng)支持AddressSanitizer和ThreadSanitizer,而4.9版本則開(kāi)始支持LeakSanitizer。

Sanitizer使用

1、AddressSanitizer的使用例子

AddressSanitizer(ASan) 是一個(gè)快速內(nèi)存檢測(cè)器,可以檢測(cè)出緩沖區(qū)溢出、使用已釋放內(nèi)存等問(wèn)題。編譯時(shí)帶上參數(shù) -fsanitize=address及-g。

(1)捕捉棧緩沖區(qū)溢出問(wèn)題:

AddressSanitizer.c:

//?微信公眾號(hào):嵌入式大雜燴
#include?<stdlib.h>

void?test_func(void)
{
????int?a[6]?=?{0};
????int?b?=?a[6];????//?棧緩沖區(qū)溢出
}?????????????????????

int?main(int?argc,?char?**argv)
{
?test_func();

?return?0;
}

編譯、運(yùn)行:

gcc?AddressSanitizer.c?-fsanitize=address?-g?-o?AddressSanitizer

執(zhí)行結(jié)果分析:

觸發(fā)了檢測(cè)錯(cuò)誤級(jí)別,終止程序并給出了程序運(yùn)行異常的原因及異常的代碼位置。

(2)捕捉使用已釋放內(nèi)存問(wèn)題:

ThreadSanitizer.c:

//?微信公眾號(hào):嵌入式大雜燴
#include?<stdlib.h>

void?test_func(void)
{
????char?*p?=?malloc(10);
????p[0]?=?1;
????free(p);
????p[0]?=?1;??//?使用已釋放內(nèi)存
}?????????????????????

int?main(int?argc,?char?**argv)
{
?test_func();

?return?0;
}

2、ThreadSanitizer的使用例子

ThreadSanitizer(TSan) 是一個(gè)數(shù)據(jù)競(jìng)爭(zhēng)檢測(cè)器,可以用來(lái)分析線程競(jìng)態(tài)、死鎖等線程相關(guān)問(wèn)題。編譯時(shí)帶上參數(shù) -fsanitize=thread及-g。

捕捉 線程間數(shù)據(jù)競(jìng)爭(zhēng) 問(wèn)題:

//?微信公眾號(hào):嵌入式大雜燴
#include?<stdio.h>
#include?<pthread.h>

int?g_counter?=?0;??//?thread1、thread2競(jìng)爭(zhēng)的數(shù)據(jù)

void?*increment(void?*arg)
{
????g_counter++;
}

void?*decrement(void?*arg)
{
????g_counter--;
}

void?test_func(void)
{
????pthread_t?thread1,?thread2;

????pthread_create(&thread1,?NULL,?increment,?NULL);
????pthread_create(&thread2,?NULL,?decrement,?NULL);

????pthread_join(thread1,?NULL);
????pthread_join(thread2,?NULL);

????printf("Counter?value:?%dn",?g_counter);
}

int?main(int?argc,?char?**argv)
{
????test_func();

????return?0;
}

編譯、運(yùn)行:

gcc?ThreadSanitizer.c?-fsanitize=thread?-g?-pthread?-o?ThreadSanitizer

執(zhí)行結(jié)果分析:

觸發(fā)了檢測(cè)警告級(jí)別,程序仍能運(yùn)行,并給出了程序運(yùn)行有風(fēng)險(xiǎn)的原因及有風(fēng)險(xiǎn)的代碼位置。

3、程序中同時(shí)存在多處風(fēng)險(xiǎn)?

上面的例子分別使用AddressSanitizer檢測(cè)器與ThreadSanitizer檢測(cè)器來(lái)檢測(cè)對(duì)應(yīng)的異常,可以較為精準(zhǔn)地檢測(cè)到對(duì)應(yīng)的異常。

如果程序中同時(shí)存在多處風(fēng)險(xiǎn)呢?

這也是比較貼近我們的實(shí)際應(yīng)用的,畢竟我們并不知道我們的代碼里有哪些可能存在的風(fēng)險(xiǎn)。這種情況我們要怎么檢測(cè)?

編譯時(shí)能同時(shí)帶上多個(gè)-fsanitize參數(shù)調(diào)用多個(gè)檢測(cè)器嗎?

可以同時(shí)帶,但有些檢測(cè)器不能同時(shí)使用。

AddressSanitizer與ThreadSanitizer檢測(cè)器不能同時(shí)使用。

但是,假如我們的程序中恰好存在address異常與thread異常呢,單獨(dú)使用AddressSanitizer檢測(cè)器、ThreadSanitizer檢測(cè)器的表現(xiàn)是怎樣的?

比如,我們把上面3個(gè)例子的代碼放在一起:

test.c:

//?微信公眾號(hào):嵌入式大雜燴
#include?<stdio.h>
#include?<stdlib.h>
#include?<pthread.h>

int?g_counter?=?0;??//?thread1、thread2競(jìng)爭(zhēng)的數(shù)據(jù)

void?*increment(void?*arg)
{
????g_counter++;
}

void?*decrement(void?*arg)
{
????g_counter--;
}

//?測(cè)試:資源競(jìng)爭(zhēng)
void?test_func(void)
{
????pthread_t?thread1,?thread2;

????pthread_create(&thread1,?NULL,?increment,?NULL);
????pthread_create(&thread2,?NULL,?decrement,?NULL);

????pthread_join(thread1,?NULL);
????pthread_join(thread2,?NULL);

????printf("Counter?value:?%dn",?g_counter);
}

//?測(cè)試:使用已釋放內(nèi)存
void?test_func1(void)
{
????char?*p?=?malloc(10);

????printf("This?is?test_func1n");

????p[0]?=?1;
????free(p);
????p[0]?=?1;??//?使用已釋放內(nèi)存
}?????

//?測(cè)試:棧緩沖區(qū)溢出
void?test_func2(void)
{
????int?a[6]?=?{0};
????int?b?=?a[6];????//?棧緩沖區(qū)溢出
}?????

int?main(int?argc,?char?**argv)
{
????test_func();
????test_func1();
?test_func2();

????return?0;
}

帶-fsanitize=thread參數(shù)編譯、運(yùn)行:

執(zhí)行結(jié)果分析:

ThreadSanitizer檢測(cè)器能正常檢測(cè)出資源競(jìng)爭(zhēng)的問(wèn)題,也檢測(cè)出了test_func1中的使用已釋放的堆內(nèi)存的問(wèn)題并以警告級(jí)別報(bào)告,但沒(méi)有檢測(cè)出test_func2的棧緩沖區(qū)溢出問(wèn)題。

是不是因?yàn)閠est_func2運(yùn)行在test_func1后面了,所以test_func2的異常沒(méi)有被ThreadSanitizer檢測(cè)器檢測(cè)出來(lái)?

我們調(diào)換個(gè)位置看看:

int?main(int?argc,?char?**argv)
{
????test_func();
?test_func2();
????test_func1();

????return?0;
}

顯然,執(zhí)行結(jié)果還是一樣的,test_func2的棧緩沖區(qū)溢出問(wèn)題還是沒(méi)有被ThreadSanitizer檢測(cè)器檢測(cè)出來(lái)。

所以,大致得出結(jié)論:當(dāng)程序里存在thread異常與address異常時(shí),使用ThreadSanitizer檢測(cè)器能準(zhǔn)確檢測(cè)到thread異常,能檢測(cè)到部分address異常。

帶-fsanitize=address參數(shù)編譯、運(yùn)行:

執(zhí)行順序:

int?main(int?argc,?char?**argv)
{
????test_func();
????test_func1();
????test_func2();

????return?0;
}

執(zhí)行結(jié)果分析:

AddressSanitizer檢測(cè)器檢測(cè)到了test_func1中的已使用釋放的堆內(nèi)存的異常并以錯(cuò)誤級(jí)別報(bào)告,并終止了程序;沒(méi)有檢測(cè)到test_func的資源競(jìng)爭(zhēng)的風(fēng)險(xiǎn);也沒(méi)有檢測(cè)到test_func2的棧緩沖區(qū)溢出的問(wèn)題,因?yàn)閳?zhí)行到test_func1的時(shí)候程序已經(jīng)被終止了,如果把test_func2放在test_func1之前運(yùn)行,就能檢測(cè)到test_func2的異常。

結(jié)論:當(dāng)程序里存在thread異常與address異常時(shí),使用AddressSanitizer檢測(cè)器能準(zhǔn)確檢測(cè)到第一個(gè)觸發(fā)的address異常,不能檢測(cè)到thread異常。

如果程序中存在多種可能存在的風(fēng)險(xiǎn)時(shí),需要使用多個(gè)檢測(cè)器單獨(dú)挨個(gè)檢測(cè)。每個(gè)檢測(cè)器都有其擅長(zhǎng)檢測(cè)的方面,可以經(jīng)過(guò)初步分析之后確定大致地方向,選擇適合地檢測(cè)器來(lái)做檢測(cè)。

以上就是關(guān)于Sanitizer的一些簡(jiǎn)單介紹及使用的分享,更多的關(guān)于Sanitizer的資料可查閱:https://github.com/google/sanitizers/wiki/

碼字不易,如果文章對(duì)你有幫助,麻煩幫忙點(diǎn)贊、關(guān)注,謝謝大家!

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
SFP-1GBT-05 1 Bel Fuse Transceiver, 1250Mbps(Tx), 1250Mbps(Rx), RJ-45 Connector, Surface Mount, ROHS COMPLIANT PACKAGE
$435.38 查看
CY14B116L-ZS25XI 1 Cypress Semiconductor Non-Volatile SRAM, 2MX8, 25ns, CMOS, PDSO44, ROHS COMPLIANT, TSOP2-44
$80.06 查看
LTC6994HS6-2#TRMPBF 1 Linear Technology LTC6994 - TimerBlox: Delay Block/ Debouncer; Package: SOT; Pins: 6; Temperature Range: -40&deg;C to 125&deg;C
$2.63 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

本公眾號(hào)專注于嵌入式技術(shù),包括但不限于C/C++、嵌入式、物聯(lián)網(wǎng)、Linux等編程學(xué)習(xí)筆記,同時(shí),公眾號(hào)內(nèi)包含大量的學(xué)習(xí)資源。歡迎關(guān)注,一同交流學(xué)習(xí),共同進(jìn)步!