登录 用户中心() [退出] 后台管理 注册
   
您的位置: 首页 >> CLQ工作室开源代码 >> 主题: [lua的坑]一个有点严重的问题,调用参数和返回值匹配错误会崩溃     [回主站]     [分站链接]
标题
[lua的坑]一个有点严重的问题,调用参数和返回值匹配错误会崩溃
clq
浏览(200) + 2023-04-07 10:37:39 发表 编辑

关键字:

[2023-04-07 10:39:02 最后更新]
[lua的坑]一个有点严重的问题,调用参数和返回值匹配错误会崩溃

在将一个 c 语言调用 lua 的函数从无返回值改为有一个字符串返回值时意外出现崩溃。

说实话我之前对 lua 印象很好的,包括它的 c 接口。使用这几年下来做完后几乎没有过崩溃的现象。

折腾了大半天发现是调用时没有正确的指定返回值的个数(lua 和 golang 一样是允许多返回值的)。在这个 c 语言函数返回时总是会崩溃。
最后确定是 以下代码导致。

```
////lua_pop(L,1); //奇怪,这个会崩溃
//lua_pop(L,1); //奇怪,这个会崩溃 //safe_lua_call 中指明有参数返回就不会

```

我对 lua 的 c 接口函数也不熟悉,多年前写好后就没怎么看过。

lua_pop(L,1);

的意义也不是太了解,其实是网上的例子即是如此。
大致是调用函数后要写一个这个。查了一下是清理堆栈的意思,而且在这里(函数返回时)就表示清理返回值。

这就要崩溃显然不太合理,感觉还是 lua 的代码应该自己处理这些错误。

不过目前来说也有个更好的处理方法,即

```
//手动清空所有栈 //比指定个数安全很多,就算参数指定不正确也不至于崩溃
lua_pop( L, -1);
```

来自 https://blog.csdn.net/f_r_e_e_x/article/details/49150721
它的取返回值代码为

printf( "调用函数后栈大小:%d\n", lua_gettop( pLua ) );
int sum = lua_tonumber( pLua, 1 );
int a = lua_tonumber( pLua, 2 );
int b = lua_tonumber( pLua, 3 );

即明确指明了返回值变量的位置,而我之前一直 copy 的代码是指定的 -1 ,猜测是栈顶吧,这在只有一个返回值的情况下确实也是正确的。

const char * s = lua_tolstring(L, -1, &len); //-1 就是栈顶值,也是 ok 的
//const char * s = lua_tolstring(L, 1, &len); //ok //指定取第几个返回值,因为 lua 是允许多返回值的,不过//成功调用后会将返回值从右到左入栈


--------------------------------------------------------
--------------------------------------------------------
Lua栈操作详解

1.让我们看看下面例子C++调用LUA函数的例子栈的使用情况

#include "stdafx.h"
int main()
{
//新建一个lua状态
lua_State *pLua = luaL_newstate();
if( nullptr == pLua )
{
return 0;
}

//得到初始化栈大小
printf( "初始化栈大小:%d\n", lua_gettop( pLua ) );

//打开所有功能库
luaL_openlibs( pLua );

//加载脚本
luaL_dofile( pLua,"test.lua" );

//将脚本中的Add函数入栈
int ret = lua_getglobal( pLua, "Add" );
if( 0 == ret )
{
return 0;
}
printf( "栈大小:%d\n", lua_gettop( pLua ) );

//函数参数从右到左入栈a = 1, b = 2
lua_pushnumber( pLua, 1 );
lua_pushnumber( pLua, 2 );
printf( "栈大小:%d\n", lua_gettop( pLua ) );
//lua_pcall会调用函数并自动清除上面和函数有关的栈
//成功调用后会将返回值从右到左入栈
lua_pcall( pLua, 2, 3, 0 );
printf( "调用函数后栈大小:%d\n", lua_gettop( pLua ) );
int sum = lua_tonumber( pLua, 1 );
int a = lua_tonumber( pLua, 2 );
int b = lua_tonumber( pLua, 3 );

printf( "sum:%d a:%d b:%d\n", sum, a, b );

//手动清空所有栈
lua_pop( pLua, -1 );//或lua_settop( pLua, 0 );
printf( "栈大小:%d\n", lua_gettop( pLua ) );
lua_close( pLua );
pLua = nullptr;

return 0;
}

test.lua脚本:

Add = function( a, b )
return a + b, a, b
end

输出结果:


2.lua_gettop()函数

该函数返回当前lua状态栈的大小

3.lua_pushxxxx()类函数

该函数往栈中添加栈数据

4.lua_pop()函数

该函数表示从当前lua状态栈中弹出几个元素
如lua_pop( pLua, 2 )表示从栈顶弹出2个元素
当第二个参数填入-1时弹出所有元素即lua_pop( pLua, -1 )

5.lua中索引index的表示方法

在使用下面的函数前必须弄懂lua中索引的表示方法
如果我们使用lua_pushnumber依次添加3个数分别1,2,3
则栈的结构为:
[3] ( 访问index为:-1 或者 3 )
[2] ( 访问index为:-2 或者 2 )
[1] ( 访问index为:-3 或者 1 )

也就是说我们要访问栈顶元素3可以使用-1或者栈大小即可访问即:
lua_tonumber( pLua, -1 ) 和 lua_tonumber( pLua, 3 )都是访问相同的元素
lua_tonumber( pLua, -2 ) 和 lua_tonumber( pLua, 2 )都是访问相同的元素
lua_tonumber( pLua, -3 ) 和 lua_tonumber( pLua, 1 )都是访问相同的元素
使用负索引从-1开始访问栈顶后面依次-1即可访问其他元素
使用正索引从栈大小开始访问栈顶后面依次-1即可访问其他元素

6.lua_settop()函数

该函数用来指定哪一个索引作为栈顶元素
在指定了新的栈顶元素之前的元素都将被移除栈
即栈结构:
[3] ( 访问index为:-1 或者 3 )
[2] ( 访问index为:-2 或者 2 )
[1] ( 访问index为:-3 或者 1 )
我们使用lua_settop( pLua, -1 )无变化因为-1这个索引本来就是栈顶索引
使用lua_settop( pLua, -2 )即-2这个元素作为新栈顶则以前-1元素值为3的旧栈顶被移除
此时栈结构:
[2] ( 访问index为:-1 或者 2 )
[1] ( 访问index为:-2 或者 1 )
如果我们一开始就使用lua_settop( pLua, -3 )则
栈结构为:
[1] ( 访问index为:-1 或者 1 )其他两个被弹出
特殊情况lua_settop( pLua, 0 )移除所有栈元素同lua_pop( pLua, -1 )效果一样
其实lua_pop就是对lua_settop封装的宏而已
最后lua_settop使用正或者负索引都是可以的,不建议lua_pop使用负索引, lua_pop( pLua, -1 ) 这种
只是特殊情况,因为它的第二个参数按道理应该是个数而不是索引容易发生意想不到的情况
为了加深理解使用下面代码自己调整lua_settop来观察:
lua_pushnumber( pLua, 1 );
lua_pushnumber( pLua, 2 );
lua_pushnumber( pLua, 3 );

lua_settop( pLua, 1 );

int a = lua_tonumber( pLua, -1 );
int b = lua_tonumber( pLua, -2 );
int c = lua_tonumber( pLua, -3 );

访问不存在的元素会返回0








总数:0 页次:1/0 首页 尾页  
总数:0 页次:1/0 首页 尾页  


所在合集/目录
lua的坑 更多



发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:



NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.

Copyright © 2005-2020 clq, All Rights Reserved
版权所有
桂ICP备15002303号-1