×

collectgarbage or for

collectgarbage(lua for 循环 内存占用扩大)

admin admin 发表于2022-09-04 23:54:21 浏览157 评论0

抢沙发发表评论

本文目录

lua for 循环 内存占用扩大


Lua 会自行管理回收内存。你上面这段代码不会有内存泄漏。
至于你退出这个脚本后,free显示的数值如果维持在原来的数值而没有减少,那是因为Linux有它自己的策略来管理内存。如果退出脚本后,free显示的占用内存还在增大,可能是其它某个软件在使用和分配内存。
你根本就不必理会Lua的内存释放,它自己会工作都非常好。
内存泄漏一般有可能出现在一些开发有缺陷的扩展模块上。Lua本身是不会有问题的。

lua的垃圾回收机制理解


Lua 垃圾回收
Lua 采用了自动内存管理。 这意味着你不用操心新创建的对象需要的内存如何分配出来, 也不用考虑在对象不再被使用后怎样释放它们所占用的内存。
Lua 运行了一个垃圾收集器来收集所有死对象 (即在 Lua 中不可能再访问到的对象)来完成自动内存管理的工作。 Lua 中所有用到的内存,如:字符串、表、用户数据、函数、线程、 内部结构等,都服从自动管理。
Lua 实现了一个增量标记-扫描收集器。 它使用这两个数字来控制垃圾收集循环: 垃圾收集器间歇率和垃圾收集器步进倍率。 这两个数字都使用百分数为单位 (例如:值 100 在内部表示 1 )。
垃圾收集器间歇率控制着收集器需要在开启新的循环前要等待多久。 增大这个值会减少收集器的积极性。 当这个值比 100 小的时候,收集器在开启新的循环前不会有等待。 设置这个值为 200 就会让收集器等到总内存使用量达到 之前的两倍时才开始新的循环。
垃圾收集器步进倍率控制着收集器运作速度相对于内存分配速度的倍率。 增大这个值不仅会让收集器更加积极,还会增加每个增量步骤的长度。 不要把这个值设得小于 100 , 那样的话收集器就工作的太慢了以至于永远都干不完一个循环。 默认值是 200 ,这表示收集器以内存分配的“两倍“速工作。
如果你把步进倍率设为一个非常大的数字 (比你的程序可能用到的字节数还大 10% ), 收集器的行为就像一个 stop-the-world 收集器。 接着你若把间歇率设为 200 , 收集器的行为就和过去的 Lua 版本一样了: 每次 Lua 使用的内存翻倍时,就做一次完整的收集。
垃圾回收器函数
Lua 提供了以下函数collectgarbage ([opt [, arg]])用来控制自动内存管理:
collectgarbage(“collect“): 做一次完整的垃圾收集循环。通过参数 opt 它提供了一组不同的功能:
collectgarbage(“count“): 以 K 字节数为单位返回 Lua 使用的总内存数。 这个值有小数部分,所以只需要乘上 1024 就能得到 Lua 使用的准确字节数(除非溢出)。
collectgarbage(“restart“): 重启垃圾收集器的自动运行。
collectgarbage(“setpause“): 将 arg 设为收集器的 间歇率。 返回 间歇率 的前一个值。
collectgarbage(“setstepmul“): 返回 步进倍率 的前一个值。
collectgarbage(“step“): 单步运行垃圾收集器。 步长“大小“由 arg 控制。 传入 0 时,收集器步进(不可分割的)一步。 传入非 0 值, 收集器收集相当于 Lua 分配这些多(K 字节)内存的工作。 如果收集器结束一个循环将返回 true 。
collectgarbage(“stop“): 停止垃圾收集器的运行。 在调用重启前,收集器只会因显式的调用运行。

CollectGarbage()适用chrome吗


chrome中没有CollectGarbage
一般把变量设为null,会自动回收。
代码可以这样写:
if ( typeof (CollectGarbage) == ’function’ ) setTimeout( “CollectGarbage()“, 1 );
-for

cocos2dx 3.11导出C++类 报错


用3.0的工具导出类到lua,自动生成代码的方法。
以前要导出c++类到lua,就得手动维护pkg文件,那简直就是噩梦,3.0以后就会感觉生活很轻松了。
下面我就在说下具体做法。
1、安装必要的库和工具包,以及配置相关环境变量,请按照cocos2d-x-3.0rc0\tools\tolua\README.mdown说得去做,不做赘述。
2、写c++类(我测试用的是cocos2d-x-3.0rc0\tests\lua-empty-test\project\Classes\HelloWorldScene.cpp)
3、写一个生成的python脚本,你不会写,没关系,我们会照猫画虎
1)进入目录cocos2d-x-3.0rc0\tools\tolua,复制一份genbindings.py,命名为genbindings_myclass.py
2)把生成目录制定到咱工程里去,打开genbindings_myclass.py把
?
1

output_dir = ’%s/cocos/scripting/lua-bindings/auto’ % project_root

改成
?
1

output_dir = ’%s/tests/lua-empty-test/project/Classes/auto’ % project_root

3)修改命令参数,把
cmd_args = {’cocos2dx.ini’ : (’cocos2d-x’, ’lua_cocos2dx_auto’), \
’cocos2dx_extension.ini’ : (’cocos2dx_extension’, ’lua_cocos2dx_extension_auto’), \
’cocos2dx_ui.ini’ : (’cocos2dx_ui’, ’lua_cocos2dx_ui_auto’), \
’cocos2dx_studio.ini’ : (’cocos2dx_studio’, ’lua_cocos2dx_studio_auto’), \
’cocos2dx_spine.ini’ : (’cocos2dx_spine’, ’lua_cocos2dx_spine_auto’), \
’cocos2dx_physics.ini’ : (’cocos2dx_physics’, ’lua_cocos2dx_physics_auto’), \
}

改成
cmd_args = {’myclass.ini’ : (’myclass’, ’lua_myclass_auto’) }

4)这时你可能问myclass.ini在哪啊,我们下来就写这个文件。原理一样,我还是照猫画虎,拿cocos2dx_spine.ini改的。
[myclass]
# the prefix to be added to the generated functions. You might or might not use this in your own
# templates
prefix = myclass

# create a target namespace (in javascript, this would create some code like the equiv. to `ns = ns || {}`)
# all classes will be embedded in that namespace
target_namespace =

android_headers
= -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include
-I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include
-I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/include
android_flags = -D_SIZE_T_DEFINED_

clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include
clang_flags = -nostdinc -x c++ -std=c++11

cocos_headers
= -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/2d
-I%(cocosdir)s/cocos/base -I%(cocosdir)s/cocos/ui
-I%(cocosdir)s/cocos/physics -I%(cocosdir)s/cocos/2d/platform
-I%(cocosdir)s/cocos/2d/platform/android
-I%(cocosdir)s/cocos/math/kazmath -I%(cocosdir)s/extensions
-I%(cocosdir)s/external -I%(cocosdir)s/cocos/editor-support
-I%(cocosdir)s

cocos_flags = -DANDROID -DCOCOS2D_JAVASCRIPT

cxxgenerator_headers =

# extra arguments for clang
extra_arguments
= %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s
%(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s
%(extra_flags)s

# what headers to parse
headers = %(cocosdir)s/tests/lua-empty-test/project/Classes/HelloWorldScene.h

# what classes to produce code for. You can use regular expressions here. When testing the regular
# expression, it will be enclosed in “^$“, like this: “^Menu*$“.
classes = HelloWorld

# what should we skip? in the format ClassName::[function function]
# ClassName is a regular expression, but will be used like this: “^ClassName$“ functions are also
# regular expressions, they will not be surrounded by “^$“. If you want to skip a whole class, just
# add a single “*“ as functions. See bellow for several examples. A special class name is “*“, which
# will apply to all class names. This is a convenience wildcard to be able to skip similar named
# functions from all classes.

skip =

rename_functions =

rename_classes =

# for all class names, should we remove something when registering in the target VM?
remove_prefix =

# classes for which there will be no “parent“ lookup
classes_have_no_parents =

# base classes which will be skipped when their sub-classes found them.
base_classes_to_skip = Ref ProcessBase

# classes that create no constructor
# Set is special and we will use a hand-written constructor
abstract_classes =

#
Determining whether to use script object(js object) to control the
lifecycle of native(cpp) object or the other way around. Supported
values are ’yes’ or ’no’.
script_control_cpp = no

改的时候要注意这些行
[myclass]
prefix = myclass
target_namespace =
headers = %(cocosdir)s/tests/lua-empty-test/project/Classes/HelloWorldScene.h
classes = HelloWorld
skip =
abstract_classes =

4、下面要自动生成代码了,打开命令行工具,cd到cocos2d-x-3.0rc0\tools\tolua下,敲入
python genbindings_myclass.py


车运行。如果前面没问题的话你会在cocos2d-x-3.0rc0\tests\lua-empty-test\project\Classes多了一
个文件夹auto,然后把里面生成lua_myclass_auto.cpp和lua_myclass_auto.hpp加入拽如工程
5、把我们生成的个module在脚本引擎初始化的时候加入lua。
编辑AppDelegate.cpp,包含lua_myclass_auto.hpp头文件,在
LuaEngine* engine = LuaEngine::getInstance();

后面加入
register_all_myclass(engine-》getLuaStack()-》getLuaState());
6、编译运行。这样HelloWorld这个类就被导出到lua了。
测试------------------------------------------------
打开hello.lua,编辑local function main()这个函数
把前面改成

local function main()
-- avoid memory leak
collectgarbage(“setpause“, 100)
collectgarbage(“setstepmul“, 5000)

local hello = HelloWorld:create()
local sceneGame = cc.Scene:create()
sceneGame:addChild(hello)
cc.Director:getInstance():runWithScene(sceneGame)

if(1==1) then
return
end
……
……
-or

如何在cocos2d c++代码中调用lua以及探究


如何在cocos2d c++代码中调用lua以及探究,有需要的朋友可以参考下。
如何在cocos2d c++代码中调用lua
在AppDelegate 中加入了
#include“Lua_extensions_CCB.h“
#include“CCLuaEngine.h“
#include“Lua_web_socket.h“
查到代码加载lua脚步引擎
官方原话注册引擎
CCLuaEngine*pEngine=CCLuaEngine::defaultEngine();
CCScriptEngineManager::sharedManager()-》setScriptEngine(pEngine);
和ccb有关的lua
CCLuaStack*pStack=pEngine-》getLuaStack();
lua_State*tolua_s=pStack-》getLuaState();
tolua_extensions_ccb_open(tolua_s);
和web_socket 相关的lua
pStack=pEngine-》getLuaStack();
tolua_s=pStack-》getLuaState();
tolua_web_socket_open(tolua_s);
pEngine-》executeScriptFile(“luaScript/controller.lua“);
结束
打开luaScript/controller.lua仔细研究
-- avoidmemory leak
collectgarbage(“setpause“,100)
collectgarbage(“setstepmul“,5000)
require“luaScript/mainMenu“
----------------
-- run
local scene =CCScene:create()
scene:addChild(CreateTestMenu())
CCDirector:sharedDirector():runWithScene(scene)
到这里如果熟悉cocos2dx 的朋友就很熟悉了
不错,这里是cocos2d中lua的使用方法和c++中调用差别不大!
但是还没有完
Cocos2dx 对lua的封装是很好的!
如果不熟悉c++与lua的绑定的代码下面的不建议看
C++与lua的绑定传送门
关于cocos2d 与 lua绑定的代码的探究
//打开“CCLuaEngine.h“
单例实现CCScripEngineProtocol
后期应该支持不仅仅只是lua的脚本引擎
头文件有很多方法
挑一个看看
virtualintexecuteNodeEvent(CCNode*pNode,intnAction);
intCCLuaEngine::executeNodeEvent(CCNode*pNode,intnAction)
{
intnHandler=pNode-》getScriptHandler();
if(!nHandler)return0;
switch(nAction)
{
casekCCNodeOnEnter:
m_stack-》pushString(“enter“);
break;
casekCCNodeOnExit:
m_stack-》pushString(“exit“);
break;
casekCCNodeOnEnterTransitionDidFinish:
m_stack-》pushString(“enterTransitionFinish“);
break;
casekCCNodeOnExitTransitionDidStart:
m_stack-》pushString(“exitTransitionStart“);
break;
casekCCNodeOnCleanup:
m_stack-》pushString(“cleanup“);
break;
default:
return0;
}
intret=m_stack-》executeFunctionByHandler(nHandler,1);
m_stack-》clean();
returnret;
}
这里是进入CCNode后的一些消息函数的处理
不管
intret=m_stack-》executeFunctionByHandler(nHandler,1);
最终是回到了CCLuaStack
调用了executeFunctionByHandler(nHandler,1);
继续探究
intCCLuaStack::executeFunctionByHandler(intnHandler,intnumArgs)
{
intret=0;
if(pushFunctionByHandler(nHandler)) /* L: ... arg1 arg2 ... func */
{
if(numArgs》0)
{
lua_insert(m_state,-(numArgs+1)); /* L: ... func arg1 arg2 ... */
}
ret=executeFunction(numArgs);
}
lua_settop(m_state,0);
returnret;
}
可以看到一些和lua与c++联系的代码了
看看这个类的初始化
boolCCLuaStack::init(void)
{
m_state=lua_open();
luaL_openlibs(m_state);
tolua_Cocos2d_open(m_state);
toluafix_open(m_state);
// Register our version of the global “print“function
constluaL_regglobal_functions={
{“print“,lua_print},
{NULL,NULL}
};
luaL_register(m_state,“_G“,global_functions);
tolua_CocoStudio_open(m_state);
#if(CC_TARGET_PLATFORM==CC_PLATFORM_IOS||CC_TARGET_PLATFORM==CC_PLATFORM_MAC)
CCLuaObjcBridge::luaopen_luaoc(m_state);
#endif
register_all_cocos2dx_manual(m_state);
register_all_cocos2dx_extension_manual(m_state);
register_all_cocos2dx_studio_manual(m_state);
// add cocos2dx loader
addLuaLoader(cocos2dx_lua_loader);
returntrue;
}
这个里的方法看名称应该是注册 coco2dx 中的类到
C++中
register_all_cocos2dx_manual(m_state);
register_all_cocos2dx_extension_manual(m_state);
register_all_cocos2dx_studio_manual(m_state);
详细看
Coco2dx-studio 先不看
头文件
lua_cocos2dx_manual.h
#ifdef__cplusplus
extern“C“{
#endif
#include“tolua++.h“
#ifdef__cplusplus
}
#endif
LUA_APIintregister_all_cocos2dx_manual(lua_State*tolua_S);
头文件
lua_cocos2dx_extensions_manual
#ifdef__cplusplus
extern“C“{
#endif
#include“tolua++.h“
#ifdef__cplusplus
}
#endif
LUA_APIintregister_all_cocos2dx_extension_manual(lua_State*tolua_S);
惊人的相似
看看tolua++.h
真相快水落石出了
这里定义了lua所以用到全部函数
这里是头部,
/* tolua
** Support code for Lua bindings.
** Written by Waldemar Celes
** TeCGraf/PUC-Rio
** Apr 2003
** $Id: $
*/
/* This code is free software; you can redistributeit and/or modify it.
** The software provided hereunder is on an“as is“ basis, and
** the author has no obligation to providemaintenance, support, updates,
** enhancements, or modifications.
*/
原来tolua也是lua封装起来的函数库,大师2003 4月就写好了
相当的牛
好上面只看了lua_cocos2dx_extensions_manual.h的头文件
cpp文件我们也一看详情
我发现注册了一些函数
但是不是全部
在CCLuaStack::init()
方法里还有
tolua_Cocos2d_open(m_state);
这个方法
相应的头文件是LuaCocos2d..h
可以打开看看详情
Luacocos2d..cpp注册了n多函数
我用注册是相对于lua而言
Luacocos2d.cpp代码贼多
有兴趣的童鞋可以看看
看来什么时间要看看cocos2d studio 的代码
紧跟时代的步伐
不能老是cocos builder
-for

lua 怎么会循环2次动作


require “Cocos2d“
require “Cocos2dConstants“
-- for CCLuaEngine traceback
function __G__TRACKBACK__(msg)
cclog(“----------------------------------------“)
cclog(“LUA ERROR: “ .. tostring(msg) .. “\n“)
cclog(debug.traceback())
cclog(“----------------------------------------“)
return msg
end
local function main()
collectgarbage(“collect“)
--避免内存泄漏
collectgarbage(“setpause“, 100)
collectgarbage(“setstepmul“, 5000)
--初始化导演
local director = cc.Director:getInstance()
local glview = director:getOpenGLView()
if glview == nil then
glview = cc.GLView:createWithRect(“HelloLua“, cc.rect(0, 0, 960, 640))
director:setOpenGLView(glview)
end
glview:setDesignResolutionSize(960, 640, cc.ResolutionPolicy.SHOW_ALL)
--显示帧率
director:setDisplayStats(true)
--设置帧率
director:setAnimationInterval(1.0 / 60)
--增加搜索路径
cc.FileUtils:getInstance():addSearchPath(“src“)
cc.FileUtils:getInstance():addSearchPath(“res“)
--创建场景
local scene = require(“GameScene“)
local settingScene = scene.create()
--运行场景
if cc.Director:getInstance():getRunningScene() then
cc.Director:getInstance():replaceScene(settingScene)
else
cc.Director:getInstance():runWithScene(settingScene)
end
end
xpcall(main, __G__TRACKBACK__)
-or

程序开发中逻辑结构需要用到的函数有哪些


比如字符串截取函数,字符串匹配函数等。
以栈顶的值作为错误对象,抛出一个 L
ua 错误。 这个函数将做一次长跳转,所以一定不会返回 (r)。
lu a_gc
[-0, +0, e]
int lu a_gc (lua_State *L, int what, int data);
控制垃圾收集器。
这个函数根据其参数 what 发起几种不同的任务:
LUA_GCSTOP: 停止垃圾收集器。
LUA_GCRESTART: 重启垃圾收集器。
LUA_GCCOLLECT: 发起一次完整的垃圾收集循环。
LUA_GCCOUNT: 返回 Lua 使用的内存总量(以 K 字节为单位)。
LUA_GCCOUNTB: 返回当前内存使用量除以 1024 的余数。
LUA_GCSTEP: 发起一步增量垃圾收集。
LUA_GCSETPAUSE: 把 data 设为 垃圾收集器间歇率 (5),并返回之前设置的值。
LUA_GCSETSTEPMUL: 把 data 设为 垃圾收集器步进倍率 (§2.5),并返回之前设置的值。
LUA_GCISRUNNING: 返回收集器是否在运行(即没有停止)。
关于这些选项的细节, collectgarbage 。
lua_getallocf
[-0, +0, –]
lua_Alloc lua_getallocf (lua_State *L, void **ud);
返回给定状态机的内存分配器函数。 如果 ud 不是 NULL , Lua 把设置内存分配函数时设置的那个指针置入 *ud 。
lua_getfield
[-0, +1, e]
int lua_getfield (lua_State *L, int index, const char *k);
把 t[k] 的值压栈, 这里的 t 是索引指向的值。 在 Lua 中,这个函数可能触发对应 “index“ 事件对应的元方法 ( )。
函数将返回压入值的类型。
lua_getextraspace
[-0, +0, –]
void *lua_getextraspace (lua_State *L);
返回一个 Lua 状态机中关联的内存块指针。 程序可以把这块内存用于任何用途;而 Lua 不会使用它。
每一个新线程都会携带一块内存, 初始化为主线程的这块内存的副本。
默认配置下,这块内存的大小为空指针的大小。 不过你可以重新编译 Lua 设定这块内存不同的大小。 (参见 luaconf.h 中的 LUA_EXTRASPACE。)
lua_getglobal
[-0, +1, e]
int lua_getglobal (lua_State *L, const char *name);
把全局变量 name 里的值压栈,返回该值的类型。
lua_geti
[-0, +1, e]
int lua_geti (lua_State *L, int index, lua_Integer i);
把 t[i] 的值压栈, 这里的 t 指给定的索引指代的值。 和在 Lua 里一样,这个函数可能会触发 “index“ 事件的元方法 ()。
返回压入值的类型。
lua_getmetatable
[-0, +(0|1), –]
int lua_getmetatable (lua_State *L, int index);
如果该索引处的值有元表,则将其元表压栈,返回 1 。 否则不会将任何东西入栈,返回 0 。
lua_gettable
[-1, +1, e]
int lua_gettable (lua_State *L, int index);
把 t[k] 的值压栈, 这里的 t 是指索引指向的值, 而 k 则是栈顶放的值。
这个函数会弹出堆栈上的键,把结果放在栈上相同位置。 和在 Lua 中一样, 这个函数可能触发对应 “index“ 事件的元方法 (4 )。
返回压入值的类型。
-for

lua中怎么捕获错误异常信息


xpcall 为什么这个方法不能满足需求 你使用xpcall 不是可以输出异常信息吗 然后你把debug.traceback()的信息写入文件不是就行了
main.lua中__G__TRACKBACK__里插入
可以将错误日志写入文件
也可以上报到服务器
package.path = package.path .. “;.app/protobuf/?.lua;./scripts/app/protobuf/?.lua;“
package.cpath = package.cpath .. ’;../protobuf/?.so’
print(package.path)
function __G__TRACKBACK__(errorMessage)
print(“__G__TRACKBACK__111“)
local path = CCFileUtils:sharedFileUtils():getWritablePath()..“log.txt“
print(path)
io.writefile(path, “\r\n“..errorMessage, “a+b“)
if “ASSERT FAILED ON LUA EXECUTE: CCHTTPRequest::getResponseString() - request not completed“ ~= tostring(errorMessage) and
“ASSERT FAILED ON LUA EXECUTE: Request not completed“ ~= tostring(errorMessage) then
print(“----------------------------------------“)
print(“LUA ERROR: “ .. tostring(errorMessage) .. “\n“)
print(debug.traceback(““, 2))
print(“----------------------------------------“)
end
end
local function startGame( ... )
collectgarbage(“setpause“, 100)
collectgarbage(“setstepmul“, 5000)
require(“app.MyApp“).new():run()
end
xpcall(startGame,__G__TRACKBACK__)
startGame()
-or