2012-05-15 50 views
2

我有使用Lua C API的問題。當pcall(C API函數)失敗時,錯誤被壓入堆棧。 lua_tostring在堆棧上顯示錯誤,但lua_gettop顯示堆棧爲空。Lua C API:pcall錯誤後堆棧爲空

#include <lua5.2/lauxlib.h> 
#include <lua5.2/lua.h> 
#include <lua5.2/lualib.h> 

int main() 
{ 
    lua_State *L = luaL_newstate(); 
    lua_pcall(L, 0, 0, 0); 
    printf("%d\n", lua_gettop(L)); // outputs 0, indicating empty stack 
    printf("%s\n", lua_tostring(L, -1)); // outputs "attempt to call a nil value", indicating non-empty stack 
} 

編譯:GCC main.c中`pkg配置--cflags lua5.2``pkg配置--libs lua5.2`

該節目顯示:試圖調用零值

lua_gettop(L)返回堆棧大小。這裏我得到0.我怎樣才能從一個空的堆棧中獲得一個字符串?

行爲與5.1版本相同。

回答

1

這已在Lua郵件列表中得到解答。行爲是正確的:您需要將一個函數推入堆棧來調用它。 luaL_newstate之後的堆棧爲空。

編輯: 該OP說:「我怎樣才能從一個空的堆棧獲得一個字符串?」。我的答案是:爲什麼你想從一個空的堆棧中獲得一些東西,當你知道它是空的,因爲lua_gettop返回0?

底線:

  • 堆棧調用lua_pcall之前是空的。這是一個錯誤。 Lua恢復了,但你不能指望它。
  • lua_pcall後堆棧空了。 Lua認爲是這樣,並通過lua_gettop告訴你。
  • 您不應該嘗試從空棧中獲取值。打印的字符串只是lua_pcall左右的垃圾,但不能指望它。
+0

不知道他爲什麼認爲他什麼都不能打電話...... –

+1

我想你誤解了這個問題。他*知道'luaL_newstate'後面的堆棧是空的,他知道*你需要在棧上推一個函數來調用它;他迫使pcall非常刻意地產生一個錯誤。問題是爲什麼在pcall *已經將錯誤消息推送到它上面之後棧頂仍然爲0?他的輸出顯示堆棧上有*錯誤消息(「嘗試調用一個零值」),但lua_gettop返回0,根據手冊[指示一個*空棧*](http:// www .lua.org /手動/ 5.1/manual.html#lua_gettop)。 – Mud

+0

@Mud,Lua API不牽手。如果你給它垃圾,你可能會得到垃圾。 'lua_pcall'假定在被調用的堆棧上有一個函數。 – lhf

0

據我所知,lua_pcall不會推送錯誤字符串。相反,它會覆蓋堆棧頂部的值(因爲總是應該有,至少是那裏的函數; p)。因此,lua_pcall(或者,更確切地說,debug.traceback,我相信)會盲目地覆蓋堆棧的頂部,而不是修改堆棧指針。

因此,當lua_pcall返回時,該值位於堆棧的頂部,但堆棧指針表示堆棧爲空(與當您調用lua_pcall時相同)。我會假設這是一個措施,以避免更嚴重的錯誤(例如,如果有內存損壞或內存不足的錯誤,我們不希望爲錯誤消息分配更多的堆棧空間,我們?)。