成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Emscripten教程之如何調(diào)試代碼(六)

cod7ce / 1284人閱讀

摘要:值啟用了更詳細的堆棧保護檢查,它以犧牲一些性能的代價提供更精確的。這種可以由任何類型的編碼錯誤引起,但表現(xiàn)為函數(shù)指針錯誤,因為在運行時的預(yù)期表中無法找到函數(shù)。

翻譯:云荒杯傾
本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請查看專欄。
也可以去作者的博客閱讀文章。
歡迎加入Wasm和emscripten技術(shù)交流群,群聊號碼:939206522。

調(diào)試Emscripten代碼的主要優(yōu)點之一是,源代碼既可以在本地平臺上進行調(diào)試,也可以使用web瀏覽器日益強大的工具集——包括調(diào)試器、分析器和其他工具。

Emscripten提供了許多幫助調(diào)試的功能和工具:

編譯器調(diào)試信息flags,允許您在已編譯的代碼中保存調(diào)試信息,甚至創(chuàng)建源映射,以便在瀏覽器中調(diào)試時可以單步調(diào)試c++源代碼。

調(diào)試模式,它產(chǎn)生調(diào)試日志和存儲 編譯時產(chǎn)生的中間文件 進行分析。

編譯器設(shè)置,使運行時檢查內(nèi)存訪問和公共分配錯誤。

還支持手動打印調(diào)試emscripten生成代碼,這在某些方面甚至比本地平臺工作效果更好。

自動調(diào)試器,它會自動地使用LLVM的中間代碼寫到內(nèi)存。

本文描述了由Emscripten提供的用于調(diào)試的主要工具和設(shè)置,以及如何調(diào)試一些Emscripten特有的問題。

調(diào)試信息

默認下,如果是優(yōu)化編譯,Emcc會刪除大部分調(diào)試信息。Optimisation級-01和以上刪除LLVM調(diào)試信息,也禁用了運行時斷言檢查。優(yōu)化級別-02以上,代碼被壓縮編譯器改編,變得幾乎不可讀。

emcc -g標志可用于在編譯的輸出中保存調(diào)試信息。默認情況下,此選項保護空白、函數(shù)名和變量名。

你可以使用五個級別中的一個來指定標記:-g0、-g1、-g2、-g3和-g4。每個級別都在最后編譯,以在編譯后的輸出中逐步提供更多的調(diào)試信息。g3標志提供與-g標志相同級別的調(diào)試信息。

g4選項提供了最多的調(diào)試信息—--—它生成了源映射(source map),允許您在Firefox、Chrome或Safari瀏覽器的調(diào)試器中查看和調(diào)試C/C++源代碼。

note:
當你既用調(diào)試flag又用優(yōu)化flag時,有些優(yōu)化可能會被禁掉,比如,如果你使用-O3 -g4 編譯,為了給你提供足夠多的調(diào)試信息,有一些-O3的優(yōu)化就得禁用掉。
調(diào)試模式(EMCC_DEBUG)

EMCC_DEBUG環(huán)境變量可以用來設(shè)置啟用/不啟用Emscripten的調(diào)試模式:

    # Linux or Mac OS X
    EMCC_DEBUG=1 ./emcc tests/hello_world.cpp -o hello.html

    # Windows
    set EMCC_DEBUG=1
    emcc tests/hello_world.cpp -o hello.html
    set EMCC_DEBUG=0

使用EMCC_DEBUG = 1設(shè)置,emcc會產(chǎn)生調(diào)試輸出文件,并為編譯器的各個編譯階段生成中間文件。
EMCC_DEBUG= 2還為每趟JavaScript優(yōu)化器遍歷(pass)生成中間文件。

調(diào)試日志和中間文件輸出到TEMP_DIR/emscripten_temp,其中TEMP_DIR默認在/tmp(/tmp的位置在.emscripten配置文件定義)。

可以對調(diào)試日志進行分析,以對每個步驟中所做的更改進行分析和檢查。

編譯器設(shè)置

Emscripten有許多可以用于調(diào)試的編譯器設(shè)置。使用emcc -s選項選擇這些設(shè)置,他們將覆蓋任何優(yōu)化標志。例如:

./emcc -01 -s ASSERTIONS=1 tests/hello_world

最重要的設(shè)置是:

ASSERTIONS=1 用于為內(nèi)存分配錯誤啟用運行時檢查(例如,寫入比分配更多的內(nèi)存)。它還定義了Emscripten如何處理程序流中的錯誤。可以將值設(shè)置為ASSERTIONS=2,以便運行額外的測試。
不優(yōu)化編譯時,ASSERTIONS=1是默認開啟的。對于優(yōu)化編譯的代碼(-01和以上級別)它是關(guān)閉的。

SAFE_HEAP= 1增加了額外的內(nèi)存訪問檢查,并將為諸如非內(nèi)聯(lián)化0(dereferencing 0)和內(nèi)存對齊等問題提供清晰的錯誤。你也可以設(shè)置SAFE_HEAP_LOG以打印SAFE_HEAP操作。

通過STACK_OVERFLOW_CHECK =1 標記在堆棧的末尾添加一個運行時的令牌值,令牌值會在某些位置被檢查,以驗證用戶代碼是否意外地寫出了堆棧的末尾。雖然溢出Emscripten堆棧不是一個安全問題(JavaScript已經(jīng)被沙箱化了),但寫出堆棧將會導(dǎo)致全局數(shù)據(jù)內(nèi)存損壞和Emscripten堆中動態(tài)分配的內(nèi)存碎片化,這使得應(yīng)用程序以意想不到的方式失敗。值STACK_OVERFLOW_CHECK = 2啟用了更詳細的堆棧保護檢查,它以犧牲一些性能的代價提供更精確的callstack。如果ASSERTIONS= 1,STACK_OVERFLOW_CHECK默認值為2,ASSERTIONS為其他值時STACK_OVERFLOW_CHECK默認不啟用。

在src/settings.js中定義了許多其他有用的調(diào)試設(shè)置。有關(guān)更多信息,請搜索“check”和“debug”關(guān)鍵字的文件。

emcc詳細輸出

用emcc -v選項編譯,將-v傳遞給LLVM,然后在工具鏈上運行Emscripten的內(nèi)部完整性檢查。

verbose模式還能啟動Emscripten的調(diào)試模式(EMCC_DEBUG)以生成編譯器的各個階段的中間文件。

手動打印調(diào)試

您還可以用printf()語句手工編寫源代碼,然后編譯并運行代碼來研究問題。

如果你對問題行有很好的了解,你可以在JavaScript添加print(新的Error().stack)代碼,以得到堆棧跟蹤。另外還有stackTrace(),它發(fā)出堆棧跟蹤,并嘗試使用c++的去除改編的函數(shù)名(如果你不想或者不需要讓c++ 函數(shù)名去除改編,你可以調(diào)用jsStackTrace())。

調(diào)試打印輸出甚至可以執(zhí)行任意的JavaScript。例如:

    function _addAndPrint($left, $right) {
            $left = $left | 0;
            $right = $right | 0;
            //---
            if ($left < $right) console.log("l
禁止優(yōu)化

有時候,編譯的時候,禁用LLVM優(yōu)化(llvm-opts)或禁用JavaScript優(yōu)化(js-opts)是很有用的。

比如說,以下命令即允許調(diào)試信息又使用-O2優(yōu)化(既llvm和js都優(yōu)化),但是又明顯關(guān)閉了js的優(yōu)化器。

./emcc -O2 --js-opts 0 -g4 tests/hello_world_loop.cpp

這樣就能產(chǎn)生相對于llvm優(yōu)化的代碼來說更易調(diào)試的js代碼:

    function _main() {
            var label = 0;
            var $puts=_puts(((8)|0)); //@line 4 "tests/hello_world.c"
            return 1; //@line 5 "tests/hello_world.c"
    }
Emscripten特有問題 內(nèi)存對齊問題

Emscripten內(nèi)存表示假定加載和存儲是對齊的。在未對齊的地址上執(zhí)行正常的加載或存儲可能會失敗。

SAFE_HEAP可以用來顯示內(nèi)存對齊問題。

一般來說,最好避免不對齊的讀寫-----他們通常是由于未定義的行為導(dǎo)致的。然而,在某些情況下,它們是不可避免的—----例如,如果要移植的代碼從一些預(yù)先存在的數(shù)據(jù)格式的打包結(jié)構(gòu)(packed structure)中讀取int。

Emscripten支持未對齊的讀寫,但它們要慢得多,而且必須在絕對必要時使用。執(zhí)行一個不對齊的讀或?qū)懩憧梢?

手動讀取單個字節(jié)并重新構(gòu)造全部值

使用emscripten_align*類型,它定義了基本類型的不對齊版本(short,int,float,double)。這些類型的所有操作都是不完全對齊的(在大多數(shù)情況下使用1個variants,這意味著沒有任何對齊)。

函數(shù)指針問題

如果你的函數(shù)指針調(diào)用得到一個abort(),那么問題是在調(diào)用時,沒有在預(yù)期的函數(shù)指針表中找到這個函數(shù)指針。

note:
nullFunc是函數(shù)指針表中用于填充空索引的函數(shù)(b0和b1是優(yōu)化編譯下它的別名)。指向無效索引的函數(shù)指針會調(diào)用這個函數(shù),然后調(diào)用abort().

有幾個可能的原因:

您的代碼調(diào)用了一個從另一個類型轉(zhuǎn)換來的函數(shù)指針(這是未定義的行為,但它確實發(fā)生在真實的代碼中)。在優(yōu)化的Emscripten輸出中,每個函數(shù)指針類型都基于它的原始簽名,存儲在一個多帶帶的表中,因此您必須調(diào)用具有相同簽名的函數(shù)指針以獲得正確的行為(更多信息參見代碼可移植性部分中的函數(shù)指針問題)。

您的代碼在空指針或者dereferencing 0上調(diào)用方法。這種bug可以由任何類型的編碼錯誤引起,但表現(xiàn)為函數(shù)指針錯誤,因為在運行時的預(yù)期表中無法找到函數(shù)。

為了調(diào)試這些問題:

使用-Werror編譯。這就把警告變成了錯誤,這些錯誤可能有用,因為一些未定義行為的情況會顯示警告。

使用-s ASSERTIONS=2,得到一些 關(guān)于被調(diào)用的函數(shù)指針和它的類型 有用的信息。

查看瀏覽器堆棧跟蹤,查看錯誤發(fā)生的地方以及應(yīng)該調(diào)用哪個函數(shù)。

使用SAFE_HEAP=1和禁用函數(shù)指針別名(aliasing_function_pointer = 0)編譯。這使得錯誤類型的函數(shù)指針 不可能在不引起錯誤的情況下 調(diào)用,換句話說就是這樣編譯會使 錯誤類型的函數(shù)指針調(diào)用 一定會報錯。調(diào)用命令:-s SAFE_HEAP=1 -s aliasing_function_pointer =0

aliasing_function_pointer = 0也很有用,因為它確保調(diào)用錯誤表中的指針地址會導(dǎo)致明顯的錯誤。如果沒有這樣的設(shè)置,這樣的調(diào)用只執(zhí)行地址上的任何函數(shù),這將很難進行調(diào)試。

死循環(huán)

無限循環(huán)導(dǎo)致您的頁面掛起。在一段時間之后,瀏覽器將通知用戶該頁面被卡住并提供停止或關(guān)閉它的選擇。

如果您的代碼中有無限循環(huán),那么找到問題代碼的一個簡單方法就是使用JavaScript profiler。在Firefox profiler中,如果代碼進入無限循環(huán),您將看到在profiler的末尾有一塊代碼重復(fù)執(zhí)行相同的操作。

AutoDebugger
警告:
這個選項主要為Emscripten核心開發(fā)者提供使用。
Emscripten代碼移植系列文章

Emscripten代碼移植主題系列文章是emscripten中文站點的一部分內(nèi)容。
本文是第三個主題第二篇文章。
第一個主題介紹代碼可移植性與限制
第二個主題介紹Emscripten的運行時環(huán)境
第三個主題第一篇文章介紹連接C++和JavaScript
第三個主題第二篇文章介紹embind
第四個主題介紹文件和文件系統(tǒng)
第六個主題介紹Emscripten如何調(diào)試代碼

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/91969.html

相關(guān)文章

  • Emscripten教程代碼可移植性與限制(一)

    摘要:教程之代碼可移植性與限制一翻譯云荒杯傾本文是專欄系列文章之一,更多文章請查看專欄。下面是正文代碼可移植性與限制幾乎可以編譯任何可移植的代碼到。如果標準機構(gòu)將共享狀態(tài)添加到中,支持多線程代碼將成為可能。 Emscripten教程之代碼可移植性與限制(一) 翻譯:云荒杯傾本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請查看專欄。也可以去作者的博客閱讀文章。歡迎...

    yangrd 評論0 收藏0
  • Emscripten教程emcc編譯命令

    摘要:優(yōu)化級別越高,編譯時間越長啟用的。允許優(yōu)化,有兩個值不允許優(yōu)化器允許使用優(yōu)化器。規(guī)定是否單獨生成一個內(nèi)存初始化文件。使生成的代碼能夠感知命令行工具。設(shè)置一個絕對路徑的白名單,以防止關(guān)于絕對路徑的警告。 emcc(Emscripten Compiler Frontend)介紹 翻譯:云荒杯傾本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請查看專欄。也可以去作...

    LiuZh 評論0 收藏0
  • Emscripten教程emcc編譯命令

    摘要:優(yōu)化級別越高,編譯時間越長啟用的。允許優(yōu)化,有兩個值不允許優(yōu)化器允許使用優(yōu)化器。規(guī)定是否單獨生成一個內(nèi)存初始化文件。使生成的代碼能夠感知命令行工具。設(shè)置一個絕對路徑的白名單,以防止關(guān)于絕對路徑的警告。 emcc(Emscripten Compiler Frontend)介紹 翻譯:云荒杯傾本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請查看專欄。也可以去作...

    Julylovin 評論0 收藏0

發(fā)表評論

0條評論

cod7ce

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<