成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

cod7ce / 1178人閱讀

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

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

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

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

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

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

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

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

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

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

調(diào)試信息

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

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

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

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

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

EMCC_DEBUG環(huán)境變量可以用來(lái)設(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會(huì)產(chǎn)生調(diào)試輸出文件,并為編譯器的各個(gè)編譯階段生成中間文件。
EMCC_DEBUG= 2還為每趟JavaScript優(yōu)化器遍歷(pass)生成中間文件。

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

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

編譯器設(shè)置

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

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

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

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

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

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

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

emcc詳細(xì)輸出

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

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

手動(dòng)打印調(diào)試

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

如果你對(duì)問題行有很好的了解,你可以在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)化

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

比如說(shuō),以下命令即允許調(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)生相對(duì)于llvm優(yōu)化的代碼來(lái)說(shuō)更易調(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)存對(duì)齊問題

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

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

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

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

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

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

函數(shù)指針問題

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

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

有幾個(gè)可能的原因:

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

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

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

使用-Werror編譯。這就把警告變成了錯(cuò)誤,這些錯(cuò)誤可能有用,因?yàn)橐恍┪炊x行為的情況會(huì)顯示警告。

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

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

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

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

死循環(huán)

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

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

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

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

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/91969.html

相關(guān)文章

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

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

    yangrd 評(píng)論0 收藏0
  • Emscripten教程emcc編譯命令

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

    LiuZh 評(píng)論0 收藏0
  • Emscripten教程emcc編譯命令

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

    Julylovin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

cod7ce

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<