A. 支持中文變數名的lua,在網上看到修改源碼就可以讓lua支持中文變數名。我學著修改了,可是改完後,
直接使用luajit就可以支持中文變數名。
--$./luajit-2.0.0-beta10
LuaJIT2.0.0-beta10--Copyright(C)2005-2012MikePall.http://luajit.org/
JIT:ONCMOVSSE2SSE3SSE4.
>你好="111"
>print(你好)
111
>
現在版本應該是支持lua5.1的。luajit的性能比lua5.1好多了。
B. lua腳本被luac編譯之後,如何反編譯或者反匯
標準的lua4.01 有「CFLuaDC」工具可以反編譯。
標準的lua5 有 「DisLua」、「luadec」 兩個工具可供選用。
--------以上三個工具在網上可搜索下載。
luajit 編譯的luac 文件 尚無反編譯工具。
C. Windows 下編譯 LuaJIT
這里使用 Visual studio 自帶的命令行工具來進行編譯,所以需要安裝好VS。
首先打開VS命令行工具。可以按 Win + S ,輸入 prompt 來找到它。如圖。
解壓 LuaJIT 源碼,並進入到解壓目錄 /src 下。輸入 msvcbuild 開始編譯。
看到 === Successfully built LuaJIT for xxxxx === 則是編譯成功了。
在解壓目錄 /src 下可以找到編譯生成的 luajit.exe 和 lua51.dll .
打開cmd。
如果沒有添加環境變數則先定位到LuaJit安裝目錄。
輸入 luajit +文件名 即可運行Lua腳本。
輸入 luajit -b +Lua腳本+目標文件名,即可編譯腳本。
D. 如何用 Valgrind 檢測使用 LuaJIT FFI 過程中的內存泄漏
memcheck工具的使用方式如下:
valgrind --tool=memcheck ./a.out
從上面的命令可以清楚的看到, 主要的命令是valgrind,而我們想使用的工具是通過'-tool'選項來指定的. 上面的『a.out』指的是我們想使用memcheck運行的可執行文件.
該工具可以檢測下列與內存相關的問題 :
未釋放內存的使用
對釋放後內存的讀/寫
對已分配內存塊尾部的讀/寫
內存泄露
不匹配的使用malloc/new/new[] 和 free/delete/delete[]
重復釋放內存
注意: 上面列出的並不很全面,但卻包含了能被該工具檢測到的很多普遍的問題.
讓我們一個一個地對上面的場景進行討論:
注意: 下面討論的所有測試代碼都應該使用gcc並且加上-g選項(用來在memcheck的輸出中生成行號)進行編譯. 就想我們之前討論過的 C程序被編譯成可執行文件, 它需要經歷四個不同的階段.
ToB藍波灣
翻譯於 1 年 前
0人頂
頂 翻譯的不錯哦!
1. 使用未初始化的內存
Code :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p;
char c = *p;
printf("\n [%c]\n",c);
return 0;
}
在上面的代碼中,我們嘗試使用未初始化的指針 『p』.
讓我們運行Memcheck來看下結果.
$ valgrind --tool=memcheck ./val
==2862== Memcheck, a memory error detector
==2862== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2862== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for right info
==2862== Command: ./val
==2862==
==2862== Use of uninitialised value of size 8
==2862== at 0x400530: main (valgrind.c:8)
==2862==
[#]
==2862==
==2862== HEAP SUMMARY:
==2862== in use at exit: 0 bytes in 0 blocks
==2862== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==2862==
==2862== All heap blocks were freed -- no leaks are possible
==2862==
==2862== For counts of detected and suppressed errors, rerun with: -v
==2862== Use --track-origins=yes to see where uninitialized values come from
==2862== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
從上面的輸出可以看到,Valgrind檢測到了未初始化的變數,然後給出了警告(上面加粗的幾行(譯者註:貌似上面沒有加粗的)).
2. 在內存被釋放後進行讀/寫
Code :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = malloc(1);
*p = 'a';
char c = *p;
printf("\n [%c]\n",c);
free(p);
c = *p;
return 0;
}
上面的代碼中,我們有一個釋放了內存的指針 『p』 然後我們又嘗試利用指針獲取值.
讓我們運行memcheck來看一下Valgrind對這種情況是如何反應的.
$ valgrind --tool=memcheck ./val
==2849== Memcheck, a memory error detector
==2849== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2849== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for right info
==2849== Command: ./val
==2849==
[a]
==2849== Invalid read of size 1
==2849== at 0x400603: main (valgrind.c:30)
==2849== Address 0x51b0040 is 0 bytes inside a block of size 1 free'd
==2849== at 0x4C270BD: free (vg_replace_malloc.c:366)
==2849== by 0x4005FE: main (valgrind.c:29)
==2849==
==2849==
==2849== HEAP SUMMARY:
==2849== in use at exit: 0 bytes in 0 blocks
==2849== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==2849==
==2849== All heap blocks were freed -- no leaks are possible
==2849==
==2849== For counts of detected and suppressed errors, rerun with: -v
==2849== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
從上面的輸出內容可以看到,Valgrind檢測到了無效的讀取操作然後輸出了警告 『Invalid read of size 1′.
另注,使用gdb來調試c程序.
3. 從已分配內存塊的尾部進行讀/寫
Code :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = malloc(1);
*p = 'a';
char c = *(p+1);
printf("\n [%c]\n",c);
free(p);
return 0;
}
在上面的代碼中,我們已經為『p』分配了一個位元組的內存,但我們在將值讀取到 『c』中的時候使用的是地址p+1.
現在我們使用Valgrind運行上面的代碼 :
$ valgrind --tool=memcheck ./val
==2835== Memcheck, a memory error detector
==2835== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2835== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for right info
==2835== Command: ./val
==2835==
==2835== Invalid read of size 1
==2835== at 0x4005D9: main (valgrind.c:25)
==2835== Address 0x51b0041 is 0 bytes after a block of size 1 alloc'd
==2835== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==2835== by 0x4005C5: main (valgrind.c:22)
==2835==
[]
==2835==
==2835== HEAP SUMMARY:
==2835== in use at exit: 0 bytes in 0 blocks
==2835== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==2835==
==2835== All heap blocks were freed -- no leaks are possible
==2835==
==2835== For counts of detected and suppressed errors, rerun with: -v
==2835== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
同樣,該工具在這種情況下也檢測到了無效的讀取操作.
4. 內存泄露
Code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = malloc(1);
*p = 'a';
char c = *p;
printf("\n [%c]\n",c);
return 0;
}
在這次的代碼中, 我們申請了一個位元組但是沒有將它釋放.現在讓我們運行Valgrind看看會發生什麼:
$ valgrind --tool=memcheck --leak-check=full ./val
==2888== Memcheck, a memory error detector
==2888== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2888== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for right info
==2888== Command: ./val
==2888==
[a]
==2888==
==2888== HEAP SUMMARY:
==2888== in use at exit: 1 bytes in 1 blocks
==2888== total heap usage: 1 allocs, 0 frees, 1 bytes allocated
==2888==
==2888== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==2888== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==2888== by 0x400575: main (valgrind.c:6)
==2888==
==2888== LEAK SUMMARY:
==2888== definitely lost: 1 bytes in 1 blocks
==2888== indirectly lost: 0 bytes in 0 blocks
==2888== possibly lost: 0 bytes in 0 blocks
==2888== still reachable: 0 bytes in 0 blocks
==2888== suppressed: 0 bytes in 0 blocks
==2888==
==2888== For counts of detected and suppressed errors, rerun with: -v
==2888== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
輸出行(上面加粗的部分)顯示,該工具能夠檢測到內存的泄露.
E. 如何閱讀luajit的代碼
為什麼要看luajit的源碼
作為目前最快的腳本語言之一,luajit確實是一個傑作,但相比原生lua僅僅幾萬行的代碼而言,luajit卻可以說是巨無霸。更要命的是,luajit之所以快,是因為大量使用了機器碼相關的技術,無論是它的機器碼編譯部分,還是位元組碼執行部分,讀起來都非常麻煩。
網上這方面的資料非常少,即使是lua社區的雲風大大也主要以分析原生lua為主,跟luajit有很多不同。萬一遇到了性能坑,或者其他難以解決的問題,需要找到原因,又不能閱讀源碼的話,就只能依賴網上其他人的結論,否則完全無從下手。
調試luajit
萬事的開頭,從能夠自己調試代碼開始
一個能調試的代碼,閱讀起來會遠遠比眼看要清晰得多。
而如果能利用visual studio進行調試,那麼對讀luajit而言還是非常有幫助的,畢竟藉助visual assist的代碼查找,能夠非常快的幫你找到你想了解的東西
luajit下面提供了一個msvcbuild.bat用於編譯luajit,但如果你需要調試的話,可以進行以下幾個步驟:
1.將luajit解壓,比如解壓到LuaJIT-2.1.0-beta2_msvc目錄
2.如果要得到精確的棧,修改LuaJIT-2.1.0-beta2_msvc\src\msvcbuild.bat,搜索/O2,將/O2改為/Od
3.在win64版本的visual studio命令行,執行一次msvcbuild.bat debug,這時會生成luajit.exe,測試一下exe是否正常。
4.用visual studio建立一個命令行工程,例如工程保存在LuaJIT-2.1.0-beta2_msvc\luajitcmd
5.把LuaJIT-2.1.0-beta2_msvc\src下所有.h和.c代碼加入工程
6.把工程的調試路徑設置為
命令:$(ProjectDir)..\..\src\luajit.exe
工作目錄:$(ProjectDir)..\..\src\
7.此時你可以正常按f5下斷點調試了
至於可以調試什麼呢?
最簡單就是寫一個lua文件,require之,執行裡面的代碼,下斷點觀察luajit的行為。
這里必須說明,luajit的執行過程中有兩大部分是沒有.c對應的:
1.有一部分代碼是通過dasm工具生成的,這部分直接通過匯編生成,沒有.c,所以沒有辦法在visual studio調試(其實也可以,但是只能匯編調試)。這些主要是lua虛擬機的代碼(是的,為了快,作者hand tune匯編的方式來寫lua虛擬機)
2.luajit會通過jit模塊編譯一部分代碼變為高度優化的機器碼,這些也是臨時生成的可執行機器碼,你只能在.c看到他們是如何生成的,但執行階段當然是沒有.c對應的。
除此以外,幾乎所有東西都可以直接vs調試:所有的編譯過程、所有的lua標准庫和api、luatable等常規數據結構、profiler,等等
下一步我們會簡單說一下代碼結構,以及結果luajit一些基本原理來說說怎麼閱讀
尤其是luajit的原理,如果對此毫無了解的情況下,閱讀其源碼是十分困難的,因為luajit從編譯到執行的過程,走了很多步,跨越了多個模塊,涉及了三種不同形式的編碼(bytecode, SSA IR, 機器碼),可見其復雜程度。
F. 為什麼用 lua 替換 luajit
1、新建一個名為1.lua的文件,裡面只有一句話print("Hello Lua"),新建一個空的out.lua腳本文件
2、開始--運行--cmd
3、luac -o out.lua 1.lua
註: luac -o [編譯後腳本名] [腳本名],必要時帶上腳本路徑,如:回車之後,再打開out.lua就可以看到編譯好的位元組碼瞭然後實驗一下,執行這個位元組碼腳本,可以看到lua原生的解釋器可以直接解析luac編譯出來的bytecode腳本,很方便!重點:
做完了以上的一系列之後,我照著這個方法編譯項目中的腳本,然後在cocos2dx環境下使用,發現不行!於是又查了一下資料,發現2dx使用的是luajit,lua原生編譯出來的bytecode和luajit是不兼容的,所以照著上面方法編譯出來的bytecode腳本無法在2dx中使用。
解決這個問題其實很簡單,就是用2dx自帶的luajit編譯lua腳本,下面附上luajit編譯bytecode的方法:
1、在cocos2d-x-2.2.3\scripting\lua\luajit\LuaJIT-2.0.1\src目錄下有個msvcbuild.bat批處理文件,需要先把luajit.exe這個東西給編譯出來。
2、打開visual studio的命令行工具,這個只要裝了vs都會有,在安裝目錄裡面可以找到。
3、用vs的命令行工具cd到luajit的src目錄
4、執行msvcbuild.bat批處理文件,編譯出luajit.exe編譯完成之後,會在src目錄下生成一系列文件,其中有一個luajit.exe接下來就可以使用luajit.exe編譯lua腳本的bytecode了:luajit -b [腳本名] [編譯後的腳本名],執行完後會在src目錄下生成一個已經編譯成bytecode的jit.lua文件
下面把編譯之後的jit.lua放在2dx中試一下,以HelloLua工程為基礎,把jit.lua放到\samples\Lua\HelloLua\Resources下,修改AppDelegate.cpp中的lua調用為std::string path = CCFileUtils::sharedFileUtils()->fullPathForFilename("jit.lua");