• 正文
  • 推薦器件
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

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

2024/04/07
2966
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

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

Sanitizer簡介

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

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

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

Sanitizer使用

1、AddressSanitizer的使用例子

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

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

AddressSanitizer.c:

//?微信公眾號:嵌入式大雜燴
#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;
}

編譯、運行:

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

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

觸發(fā)了檢測錯誤級別,終止程序并給出了程序運行異常的原因及異常的代碼位置。

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

ThreadSanitizer.c:

//?微信公眾號:嵌入式大雜燴
#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) 是一個數(shù)據(jù)競爭檢測器,可以用來分析線程競態(tài)、死鎖等線程相關(guān)問題。編譯時帶上參數(shù) -fsanitize=thread及-g。

捕捉 線程間數(shù)據(jù)競爭 問題:

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

int?g_counter?=?0;??//?thread1、thread2競爭的數(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;
}

編譯、運行:

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

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

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

3、程序中同時存在多處風(fēng)險?

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

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

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

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

可以同時帶,但有些檢測器不能同時使用。

AddressSanitizer與ThreadSanitizer檢測器不能同時使用。

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

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

test.c:

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

int?g_counter?=?0;??//?thread1、thread2競爭的數(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);
}

//?測試:使用已釋放內(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)存
}?????

//?測試:棧緩沖區(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ù)編譯、運行:

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

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

是不是因為test_func2運行在test_func1后面了,所以test_func2的異常沒有被ThreadSanitizer檢測器檢測出來?

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

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

????return?0;
}

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

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

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

執(zhí)行順序:

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

????return?0;
}

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

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

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

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

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

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

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險等級 參考價格 更多信息
ASSR-1218-003E 1 Avago Technologies TRANSISTOR OUTPUT SOLID STATE RELAY, 3750V ISOLATION-MAX, ROHS COMPLIANT, SURFACE MOUNT, SOP-4
$1.93 查看
CSTCE8M00G52A-R0 1 Murata Manufacturing Co Ltd Ceramic Resonator, 8MHz Nom, ROHS COMPLIANT, CERAMIC PACKAGE-3

ECAD模型

下載ECAD模型
$1.03 查看
AFBR-57G5MZ 1 Broadcom Limited Transceiver,
暫無數(shù)據(jù) 查看

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

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