【Linux】使用AddressSanitizer分析內存非法使用問題

文章目錄

      • 1 為什么需要AddressSanitizer?
      • 2 如何使用AddressSanitizer
      • 3 AddressSanitizer的原理
      • 4 總結

1 為什么需要AddressSanitizer?

Valgrind是比較常用的內存問題定位工具,既然已經有了Valgrind,為什么還需要AddressSanitizer呢?

與Valgrind相比,AddressSanitizer存在以下優勢:

  • Valgrind通過模擬CPU來檢測內存錯誤,導致會以較慢的速度運行程序;而AddressSanitizer是在編譯階段插入檢查的邏輯,執行速度比Valgrind快很多
  • Valgrind是一個獨立的工具,可以使用在任何程序上;而AddressSanitizer與編譯器緊密集成,可以在構建時自動啟用
  • 在錯誤信息的展示上,AddressSanitizer提供的錯誤信息比Valgrind容易理解
  • AddressSanitizer作為編譯器的一部分,通過編譯選項啟用;而Valgrind作為獨立的工具,需要更多的配置和學習才能使用
  • AddressSanitizer通過編譯時插樁和運行時檢查來檢測內存錯誤,誤報率較低

從使用場景來說,AddressSanitizer專注于發現內存未釋放訪問非法內存的問題。

2 如何使用AddressSanitizer

從gcc 4.8開始,AddressSanitizer稱為gcc的一部分,但是,gcc 4.8的AddressSanitizer沒有符號信息,建議使用gcc 4.9及以上版本。

首先使用AddressSanitizer來檢測下常見的內存問題。

用例一:未正確釋放內存

#include <iostream>int main() {int *ptr = new(int);*ptr = 0;std::cout << *ptr << std::endl;
}

上述代碼申請了一個int的空間,但是沒有釋放,編譯該程序:g++ -fsanitize=address -fno-omit-frame-pointer -o main main.cpp,然后直接執行:

0=================================================================
==711759==ERROR: LeakSanitizer: detected memory leaksDirect leak of 4 byte(s) in 1 object(s) allocated from:#0 0x7f37f92201c7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99#1 0x55581dc742be in main (/root/asan/main+0x12be)#2 0x7f37f8c54fcf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s).

結果比Valgrind更好理解:

  • 出現了內存泄漏
  • 導致內存泄漏的內存分配的調用棧
  • 總結,在一次分配過程中泄漏了4字節

用例二:分配的內存未使用配對的函數釋放

#include <iostream>int main() {int *ptr = new(int);*ptr = 0;free(ptr);
}
=================================================================
==711960==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new vs free) on 0x602000000010#0 0x7f8ef531c517 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127#1 0x5571e62742ef in main (/root/asan/main+0x12ef)#2 0x7f8ef4d52fcf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58#3 0x7f8ef4d5307c in __libc_start_main_impl ../csu/libc-start.c:409#4 0x5571e62741c4 in _start (/root/asan/main+0x11c4)0x602000000010 is located 0 bytes inside of 4-byte region [0x602000000010,0x602000000014)
allocated by thread T0 here:#0 0x7f8ef531e1c7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99#1 0x5571e627429e in main (/root/asan/main+0x129e)#2 0x7f8ef4d52fcf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58SUMMARY: AddressSanitizer: alloc-dealloc-mismatch ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127 in __interceptor_free
==711960==HINT: if you don't care about these errors you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0
==711960==ABORTING

結果也可以直接看出來:

  • alloc-dealloc-mismatch(operator new vs free):分配和銷毀不匹配
  • 分配和銷毀的調用棧

用例三:使用已經被回收的內存

#include <iostream>int main() {int *ptr = new(int);*ptr = 0;delete(ptr);*ptr = 1;
}
=================================================================
==712018==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000010 at pc 0x560c4aac2331 bp 0x7ffd02a2d040 sp 0x7ffd02a2d030
WRITE of size 4 at 0x602000000010 thread T0#0 0x560c4aac2330 in main (/root/asan/main+0x1330)#1 0x7ff2fbc22fcf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58#2 0x7ff2fbc2307c in __libc_start_main_impl ../csu/libc-start.c:409#3 0x560c4aac21c4 in _start (/root/asan/main+0x11c4)0x602000000010 is located 0 bytes inside of 4-byte region [0x602000000010,0x602000000014)
freed by thread T0 here:#0 0x7ff2fc1ef22f in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:172#1 0x560c4aac22f9 in main (/root/asan/main+0x12f9)#2 0x7ff2fbc22fcf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58previously allocated by thread T0 here:#0 0x7ff2fc1ee1c7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99#1 0x560c4aac229e in main (/root/asan/main+0x129e)#2 0x7ff2fbc22fcf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58SUMMARY: AddressSanitizer: heap-use-after-free (/root/asan/main+0x1330) in main
Shadow bytes around the buggy address:0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[fd]fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):Addressable:           00Partially addressable: 01 02 03 04 05 06 07 Heap left redzone:       faFreed heap region:       fdStack left redzone:      f1Stack mid redzone:       f2Stack right redzone:     f3Stack after return:      f5Stack use after scope:   f8Global redzone:          f9Global init order:       f6Poisoned by user:        f7Container overflow:      fcArray cookie:            acIntra object redzone:    bbASan internal:           feLeft alloca redzone:     caRight alloca redzone:    cbShadow gap:              cc
==712018==ABORTING

會輸出heap-use-after-free類型的結果:

  • 結果包含內存分配、釋放以及寫已經釋放的內存的調用棧
  • 在SUMMARY下面出現兩塊數據,這個就涉及到AddressSanitizer的實現

3 AddressSanitizer的原理

前面說過,AddressSanitizer主要的使用場景是內存未釋放訪問非法內存,為了能夠發現這兩種情況,需要為內存保存一些狀態信息。

為了能夠為內存保存狀態信息,AddressSanitizer會用自己的運行時庫替換默認的malloc/free,將需要操作內存的代碼進行替換。

例如,如果是讀操作:

... = *address;

則在訪問內存前執行檢查:

if (IsPoisoned(address)) {ReportError(address, kAccessSize, kIsWrite);
}
... = *address;

如果是寫操作:

*address = ...;

則在寫操作之前進行檢查:

if (IsPoisoned(address)) {ReportError(address, kAccessSize, kIsWrite);
}
*address = ...;

其中的IsPoisoned()函數就是用來檢查內存地址是否合法

AddressSanitizer使用影子內存的機制進行內存地址的合法性檢查:對程序實際使用的內存使用額外的字節來存儲它的狀態信息。

使用1個字節存儲實際使用的8個字節的狀態:

  • 8個字節的數據可讀寫,則1個字節的值為0
  • 8個字節的數據不可讀寫,則1個字節的值為負數,不同的值表示不同類型的內存,如0xfa表示堆左邊的redzone(redzone是在正常可以使用的內存兩側的邊界),0xf1表示棧左邊的redzone
  • 8個字節中前k個字節可讀寫,后8-k個字節不可讀寫,則1個字節的值為k

因此,IsPoisoned()函數就是檢查地址對應的影子內存中的狀態是否可以訪問,如果不能訪問,則出現訪問非法內存的問題,如果訪問的地址的影子內存是redzone,則說明出現內存訪問越界的問題。

基于上述描述,再來看上面heap-use-after-free的輸出的后面部分的內容:

Shadow bytes around the buggy address:0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[fd]fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):Addressable:           00Partially addressable: 01 02 03 04 05 06 07 Heap left redzone:       faFreed heap region:       fdStack left redzone:      f1Stack mid redzone:       f2Stack right redzone:     f3Stack after return:      f5Stack use after scope:   f8Global redzone:          f9Global init order:       f6Poisoned by user:        f7Container overflow:      fcArray cookie:            acIntra object redzone:    bbASan internal:           feLeft alloca redzone:     caRight alloca redzone:    cbShadow gap:              cc
==712018==ABORTING

第二部分是圖例,也就是影子內存中不同的值代表的含義,例如,fd表示已經被釋放的內存。

第一部分顯示的就是影子內存的數據,出現了fd表示已經被釋放的內存,對該內存再次訪問就會出現heap-use-after-free問題。

下面再看一個棧溢出的例子:

#include <iostream>
#include <string.h>int main() {int arr1[10];int arr2[12];memcpy(arr1, arr2, 12*sizeof(int));
}

結果:

=================================================================
==714984==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe915be528 at pc 0x7f22667182c3 bp 0x7ffe915be4d0 sp 0x7ffe915bdc78
WRITE of size 48 at 0x7ffe915be528 thread T0#0 0x7f22667182c2 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827#1 0x5620a92e0349 in main (/root/asan/main+0x1349)#2 0x7f22661c8fcf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58#3 0x7f22661c907c in __libc_start_main_impl ../csu/libc-start.c:409#4 0x5620a92e01c4 in _start (/root/asan/main+0x11c4)Address 0x7ffe915be528 is located in stack of thread T0 at offset 72 in frame#0 0x5620a92e0298 in main (/root/asan/main+0x1298)This frame has 2 object(s):[32, 72) 'arr1' (line 5)[112, 160) 'arr2' (line 6) <== Memory access at offset 72 partially underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy
Shadow bytes around the buggy address:0x1000522afc50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x1000522afc60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x1000522afc70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x1000522afc80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x1000522afc90: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
=>0x1000522afca0: 00 00 00 00 00[f2]f2 f2 f2 f2 00 00 00 00 00 000x1000522afcb0: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 000x1000522afcc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x1000522afcd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x1000522afce0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x1000522afcf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):Addressable:           00Partially addressable: 01 02 03 04 05 06 07 Heap left redzone:       faFreed heap region:       fdStack left redzone:      f1Stack mid redzone:       f2Stack right redzone:     f3Stack after return:      f5Stack use after scope:   f8Global redzone:          f9Global init order:       f6Poisoned by user:        f7Container overflow:      fcArray cookie:            acIntra object redzone:    bbASan internal:           feLeft alloca redzone:     caRight alloca redzone:    cbShadow gap:              cc
==714984==ABORTING

結果表明,這是一個stack-buffer-overflow的錯誤,對于棧內存來說,也會給出分配棧空間的變量的地方以及對棧內存出現非法訪問的調用棧,還分別給出了兩個變量的位置。

下面的影子內存可以看出:

  • f1是棧左紅區,f2是棧中紅區,f3是棧右紅區
  • 所有的棧空間都處于f1和f3之間,變量之間用f2隔開
  • arr1是10個int,也就是40個字節,使用5個影子字節,即影子內存中=>所在行的左側的5個字節
  • arr2是12個int,也就是48個字節,使用6個影子字節,即影子內存中=>所在行的左側的6個字節
  • [f2]表明訪問棧中紅區,出現棧的訪問越界

4 總結

AddressSanitizer是進行內存異常使用分析的工具,該工具已經集成到編譯器中,因此,只能用于分析C/C++語言的內存問題分析。與Valgrind相比,運行速度更快,但是,從場景來說,AddressSanitizer主要用于檢測內存的非法使用,當然也包括內存未正確釋放的問題,而Valgrind則可以分析出導致內存增長的調用棧。

因此:

  • 如果出現內存偏高的問題,可以使用Valgrind工具分析
  • 如果出現內存導致的core問題,可以使用gdb的watchpoint或者AddressSanitizer分析

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13579.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13579.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13579.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java 通過 microsoft graph 調用outlook(三)

這次會添加一個Reply接口&#xff0c; 并且使用6.10.0版本 直接上代碼 一&#xff0c; POM <!-- office 365 --><dependency><groupId>com.microsoft.graph</groupId><artifactId>microsoft-graph</artifactId><version>6.1…

域內 dcsync 權限維持

一、原理 DCSync 是域滲透中經常會用到的技術&#xff0c;其被整合在了 Mimikatz 中。在 DCSync 功能出現之前&#xff0c;要想獲得域用戶的哈希&#xff0c;需要登錄域控制器&#xff0c;在域控制器上執行代碼才能獲得域用戶的哈希。 Mimikatz的DCSync 功能&#xff1a; 該…

java8總結

java8總結 java8新特性總結1. 行為參數化2. lambda表達式2.1 函數式接口2.2 函數描述符 3. Stream API3.1 付諸實踐 java8新特性總結 行為參數化lambda表達式Stream Api 1. 行為參數化 定義&#xff1a;行為參數化&#xff0c;就是一個方法接受多個不同的行為作為參數&#x…

harmony 文件上傳

圖片上傳 1&#xff0c; 獲取文件&#xff0c;這里指的是圖片 在鴻蒙內部有一個API pick選擇器&#xff0c;實現文件保存和文件選擇的功能&#xff0c; 使用pick對象創建PhotoViewPicker實例 傳入必要的參數&#xff0c;如選擇圖片的數量&#xff0c;和彈出窗口的位置&#xf…

【機器學習】前沿探索,如何讓前端開發更加搞笑

在當今數字化時代&#xff0c;機器學習的崛起為前端開發帶來了巨大的機遇和挑戰。隨著人工智能和數據科學的不斷進步&#xff0c;前端工程師不再局限于傳統的界面設計和交互體驗&#xff0c;而是開始探索如何將機器學習技術融入到他們的工作中&#xff0c;以創造更加智能、個性…

面了一個程序員,因為6休1拒絕了我

人一輩子賴以生存下去的主要就考慮三件事&#xff0c;職業&#xff0c;事業&#xff0c;副業&#xff0c;有其1-2都是很不錯的。如果還沒到40歲&#xff0c;那不妨提前想下自己可能遇到的一些情況&#xff0c;提前做一些準備&#xff0c;未雨綢繆些。 今年整體就業大環境也一般…

【手寫大跟堆詳解】

文章目錄 大跟堆介紹大跟堆的結構大跟堆的應用場景大跟堆的代碼實現 大跟堆介紹 大根堆&#xff08;Max Heap&#xff09;是一種特殊的二叉樹結構&#xff0c;它滿足以下兩個條件&#xff1a; 1.完全二叉樹&#xff1a;大根堆是一棵完全二叉樹&#xff0c;即除了最后一層外&am…

一分鐘快速排序

這個 quick_sort 函數是一個實現快速排序&#xff08;Quicksort&#xff09;算法的遞歸函數。快速排序是一種高效的排序算法&#xff0c;通常用于對大規模數據集進行排序。以下是對該函數的詳細解釋&#xff1a; 函數簽名 void quick_sort(int q[], int l, int r)q[]&#xf…

Qt_電腦wifi相關操作

項目描述: 在做項目時用到了獲取wifi的操作。在網上查找了好久資料,這里做一些總結。 這里有顯示當前電腦wifi連接狀態,列出wifi列表,連接斷開wifi等函數。歡迎大家留言添加文章內容。 使用范圍: windows電腦(中文的環境) 使用技術:windows的cmd命令。和對字符串的解析…

C語言學習筆記--運算符與表達式(7521字爆肝)

上午好&#xff0c;本來想上午改簡歷下午學習c語言的&#xff0c;但想了一下上午精力充沛還是用來學習比較好&#xff0c;雖然現在失業了&#xff0c;但住在我姨家有吃有住的&#xff0c;再次感謝我姨&#xff0c;我要抓緊時間修改簡歷&#xff0c;然后找個工作搬出去&#xff…

【回憶版】數據科學思維與大數據智能分析 2024考試

填空&#xff08;18分&#xff09;18個 1.對數變換對大數值的范圍進行壓縮&#xff0c;對小數值的范圍進行擴展 2.提取出大量高頻率項與低頻率項相關聯的虛假模式&#xff0c;即交叉支持&#xff08;cross-support&#xff09;模式 3.信息論中&#xff08;&#xff09; 4.幾種…

[數據集][目標檢測]彈簧上料檢測數據集VOC+YOLO格式142張2類別

數據集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路徑的txt文件&#xff0c;僅僅包含jpg圖片以及對應的VOC格式xml文件和yolo格式txt文件) 圖片數量(jpg文件個數)&#xff1a;142 標注數量(xml文件個數)&#xff1a;142 標注數量(txt文件個數)&#xff1a;142 標注類別…

yolov8訓練自己數據集時出現loss值為nan。

具體原因目前暫未尋找到。 解決辦法 將參數amp改成False即可。 相關資料&#xff1a; https://zhuanlan.zhihu.com/p/165152789 https://github.com/ultralytics/ultralytics/issues/1148

【BUG】Edge|聯想電腦 Bing 搜索報錯“Ref A: 亂碼、 Ref B:亂碼、Ref C: 日期” 的解決辦法

文章目錄 省流版前言解決辦法 詳細解釋版前言問題描述與排查過程解決辦法與總結 省流版 前言 我也不清楚咋滴了&#xff0c;Bing 搜索突然偶爾報錯&#xff1a; 換了代理關了插件都報錯。 參考&#xff1a; 我在用bing搜索時出現了如下代碼&#xff0c;導致bing無法使用&am…

nginx proxy_set_header詳解

proxy_set_header 是 Nginx 配置中的一個重要指令&#xff0c;特別是在使用 Nginx 作為反向代理時。該指令允許你修改由 Nginx 傳遞給代理后端的請求頭。這對于確保后端應用程序能夠接收到正確的客戶端信息&#xff08;如 IP 地址、主機名等&#xff09;以及控制緩存行為等場景…

1 計算機硬件-CPU-校驗碼-存儲系統-輸入輸出設備-總線結構

計算機硬件 考情分析&#xff1a;趨勢很小&#xff0c;22年考過&#xff0c;根據趨勢以后考的可能較小 基本組成&#xff1a;運算器&#xff0c;控制器&#xff0c;儲存器&#xff0c;輸入設備&#xff0c;輸出設備運算器和控制器也統稱為中央處理單元&#xff08;CPU&#xf…

【算法訓練 day37 檸檬水找零、長度最小的子數組、用最少數量的箭引爆氣球】

目錄 一、檸檬水找零-LeetCode 860思路實現代碼個人問題總結 二、根據身高重建隊列-LeetCode 406思路實現代碼個人問題總結 三.用最少數量的箭引爆氣球-LeeCode 406思路實現代碼個人問題總結 一、檸檬水找零-LeetCode 860 Leecode鏈接: leetcode 860 文章鏈接: 代碼隨想錄 視頻…

解鎖Nginx跨域謎題:3步打造安全高效的CORS策略

Nginx作為一款強大的Web服務器和反向代理服務器&#xff0c;經常被用于處理跨域資源共享&#xff08;CORS&#xff0c;Cross-Origin Resource Sharing&#xff09;策略&#xff0c;以允許或限制不同源之間的資源請求。CORS是一種安全策略&#xff0c;用于決定Web瀏覽器是否應允…

深度學習——圖像分類(CNN)—測試模型

測試模型 1.導入必要的庫2.加載測試數據集3.假設CSV文件中的圖像文件名是完整的路徑4.隨機選擇一張圖片進行展示5.加載圖像6.使用模型進行預測7.設置模型的預測結果8.計算準確率9.指定test文件夾路徑10.讀取名為image_path的圖片11.加載圖像12.檢查圖像是否為空 訓練的模型是上…

eNSP學習——OSPF單區域配置

目錄 相關命令 實驗背景 實驗目的 實驗步驟 實驗拓撲 實驗編址 實驗步驟 1、基礎配置 2、部署單區域OSPF網絡 3、檢查OSPF單區域的配置結果 OSPF——開放式最短路徑優先 基于鏈路狀態的協議&#xff0c;具有收斂快、路由無環、擴展性好等優點&#xff1b; 相關命令 […