为了账号安全,请及时绑定邮箱和手机立即绑定

我的修改方案就是直接将 fflush(NULL)这句去掉,这样做会不会有什么风险?

我的修改方案就是直接将 fflush(NULL)这句去掉,这样做会不会有什么风险?

C
翻过高山走不出你 2023-03-04 13:09:37
c程序中使用lua5.3.2库来实现程序与lua脚本的调用,设计概要:1. 多线程调用lua的接口来实现对lua脚本的调用2. 多线程调用system实现其他任务这样做概率性的会出现程序死锁问题,下面是部分的堆栈信息:Thread 8 (Thread 0x7f7ae46f0700 (LWP 14392)):#0 0x00007f7b7ab03d1c in __lll_lock_wait_private () from /lib64/libc.so.6#1 0x00007f7b7aa7653d in _L_lock_121 () from /lib64/libc.so.6#2 0x00007f7b7aa74103 in __GI__IO_un_link () from /lib64/libc.so.6#3 0x00007f7b7aa6611d in fclose@@GLIBC_2.2.5 () from /lib64/libc.so.6#4 0x000000000046b2db in io_fclose ()#5 0x000000000045c1dc in luaD_precall ()#6 0x00000000004665a5 in luaV_execute ()#7 0x000000000045c59c in luaD_call ()Thread 4 (Thread 0x7f7ae26ec700 (LWP 14396)):#0 0x00007f7b7ab03d1c in __lll_lock_wait_private () from /lib64/libc.so.6#1 0x00007f7b7aa76640 in _L_lock_4452 () from /lib64/libc.so.6#2 0x00007f7b7aa75a08 in _IO_flush_all_lockp () from /lib64/libc.so.6#3 0x000000000046ba63 in io_popen ()Thread 181 (Thread 0x7f7b3af9d700 (LWP 14197)):#0 0x00007f7b7ab03d1c in __lll_lock_wait_private () from /lib64/libc.so.6#1 0x00007f7b7aa76728 in _L_lock_6097 () from /lib64/libc.so.6#2 0x00007f7b7aa7647f in __GI__IO_list_lock () from /lib64/libc.so.6#3 0x00007f7b7aabd087 in fork () from /lib64/libc.so.6#4 0x000000000044a302 in systemEx 经过定位,io_popen调用了l_popen#define l_popen(L,c,m) (fflush(NULL), popen(c,m))问题就在这句 fflush(NULL),这是这个操作导致了死锁
查看完整描述

1 回答

?
长风秋雁

TA贡献1757条经验 获得超7个赞

在C中调用Lua函数的API主要由以下几个:
(1)void lua_call (lua_State *L, int nargs, int nresults);
函数调用,nargs表示参数的个数,nresults表示返回值的个数
首先将lua函数压栈,然后将参数依次压栈,最后调用函数即可
函数调用时,参数和函数都会pop出栈,调用返回后,结果会push进栈
nresults==LUA_MULTRET,所有的返回值都会push进栈
nresults!=LUA_MULTRET,返回值个数根据nresults来调整
Lua语句:
a = f("how", t.x, 14)
在C中的实现:
lua_getglobal(L, "f");        // 函数入栈
lua_pushstring(L, "how");     // 参数1入栈
lua_getglobal(L, "t");       // 表t入栈
lua_getfield(L, -1, "x");      // 参数2入栈
lua_remove(L, -2);        // 跳t出栈
lua_pushinteger(L, 14);     // 参数3入栈
lua_call(L, 3, 1);        // 调用函数,参数和函数都会出栈
lua_setglobal(L, "a");     // 给a赋值,栈顶出栈
上述代码执行完毕后,堆栈状态恢复原样。
(2)int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);
函数调用,在安全模式下,并且可以添加错误处理函数。
如果调用期间发生error,lua_pcall会捕获之,然后push stack一个错误信息(会先将函数和参数pop出栈),并且返回一个error code(非0的一个值)。
发生error时,如果指定了错误处理函数,会在error message入栈前调用错误处理函数,具体由msgh参数来决定:
(1)msgh==0,不指定错误处理函数,入栈信息不变;
(2)msgh!=0,msgh表示错误处理函数的堆栈index,错误处理函数会以error message为参数,并将返回的新的error
message入栈。主要用来给error 
message添加  更多的debug信息,比如堆栈跟踪,因为这些信息在pcall调用完之后是收集不到的。
函数返回代码:
LUA_OK(0):调用成功
LUA_ERRRUN:runtime error
LUA_ERRMEM:内存分配错误,这种情况下不会调用错误处理函数
LUA_ERRERR:调用错误处理函数时出错,当然,不会再进一步调用错误处理函数
LUA_ERRGCMM:调用metamethod.__gc时报错,由gc引起,和函数本身没关系
(3)int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k);
函数调用,在安全模式下,并且允许函数yield


查看完整回答
反对 回复 2023-03-06
  • 1 回答
  • 0 关注
  • 171 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号