为啥lua语言中使用全局变量就会造成内存泄漏呢??

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥lua语言中使用全局变量就会造成内存泄漏呢??相关的知识,希望对你有一定的参考价值。

导致多线程不安全。不一定会造成泄露。在创建多个lua虚拟机的时候会2个线程同时操作一个变量。这是你代码设计问题
至于如何发现内存泄漏,也简单说一下,如果是陌生代码,或者虽然是你的,但你也懒得猜哪里泄漏了,那么请参考云风的泄漏检查工具:http://blog.codingnow.com/2012/12/lua_snapshot.html
如果代码的大体逻辑比较熟悉,则可以使用弱引用表来检查是否存在泄漏。通常产生泄漏的都是一些被反复创建的类型,例如游戏里的怪物(打死了就刷一个新的)、玩家(有人登录就要创建一个新的玩家对象),这些东西由于在程序运行周期里反复地创建、销毁,所以一旦有销毁不干净的情况,就容易导致明显的内存泄漏。那么探查这些对象是否存在泄漏,就有一个较为简单的办法,即:弱引用表。(如果你不知道什么是弱引用,请点击这里)。
为了发现内存泄漏,我们可以创建一个全局的弱引用table,使其key为弱引用,然后在每次创建那些可能存在泄漏的对象的时候,都放入这个table,让其作为key,value通常我会用当前时间。由于弱引用的性质,如果其他引用都消失了,那么在弱引用table中对这个对象的引用也会消失(变成nil),反之,只要还有其它任何一个引用存在,这个弱引用表中对这个对象的引用就继续存在。依赖这个特性,当程序已经跑过释放对象的逻辑后,如果这个表中还存在有这个对象的引用,那么这个对象肯定就是泄漏了。

说完了发现泄漏的方法,接下来轮到如何解决。其实我本来也想尝试一下云大的snapshot,奈何这个项目用的是luajit,莫名其妙地不能require,时间紧迫,无法研究,只好作罢,另寻他法。不料一顿google下来除了snapshot之外几乎没有一个像样的解决方案。情急之下,只好研究原理,自己动手,下面请看干货:
既然内存泄漏一定有引用没清,那么基于lua的特性,这个引用一定存在于_G下面的某个table或者function的upvalue中(想不明白这个的同学请想明白再往下看),既然第一步的方法可以定位泄漏,而且还可以得到泄漏对象的引用,那么事情就好办多了。无非就是得到引用之后遍历_G,找到这个引用,并且把层级列出来,方便知道这个东西到底在哪里,想解决就好办的多了。实现方法就不多说了,看代码最直接。下面代码中,调用findObjectInGlobal(泄漏对象的引用),即可找到一切非局部变量的归属关系。
local findedObjMap = nil
function _G.findObject(obj, findDest)
if findDest == nil then
return false
end
if findedObjMap[findDest] ~= nil then
return false
end
findedObjMap[findDest] = true

local destType = type(findDest)
if destType == "table" then
if findDest == _G.CMemoryDebug then
return false
end
for key, value in pairs(findDest) do
if key == obj or value == obj then
_info("Finded Object")
return true
end
if findObject(obj, key) == true then
_info("table key")
return true
end
if findObject(obj, value) == true then
_info("key:["..tostring(key).."]")
return true
end
end
elseif destType == "function" then
local uvIndex = 1
while true do
local name, value = debug.getupvalue(findDest, uvIndex)
if name == nil then
break
end
if findObject(obj, value) == true then
_info("upvalue name:["..tostring(name).."]")
return true
end
uvIndex = uvIndex + 1
end
end
return false
end

function _G.findObjectInGlobal(obj)
findedObjMap =
setmetatable(findedObjMap, __mode = "k")
_G.findObject(obj, _G)
end
参考技术A 会导致多线程不安全。在创建多个lua虚拟机的时候会2个线程同时操作一个变量。这是你代码设计问题。不一定会造成泄露。本回答被提问者和网友采纳

前端开发四

7、闭包问题

闭包:函数能被外部调用到,则该作用连上的所有变量都会被保存下来。

作用:①可以读取函数内部的变量;②相当于划出了一块私有作用域,避免数据污染;③让变量始终保存在内存中

使用全局变量被认为是不好的习惯,而且容易造成错误并且维护成本较高,所以js可以采用闭包的方式读取函数的内部变量。但是如果大量使用闭包就会造成过多的变量始终保存在内存中,会造成内存泄漏。

一个简单的闭包例子:

function f1(){
  var n=999;
  function f2(){
    alert(n);
  }
  return f2;
}
var result=f1();
result(); // 999

9、模块化编程

①AMD(异步模块定义) requirejs

defined(id,deps,factory)
require([dependency],function(){})

异步加载,浏览器不会失去响应

它指定的回调函数,只有前面的模块都加载完成后,才会运行,解决了依赖性问题

②CMD(通用模块定义) seajs

模块定义方式和模块加载时机处理不同

defined(id,deps,factory)
function(require,exports,module)
module.exports = ______;

③区别:AMD依赖前置,在定义模块的时候就要声明其依赖的模块;CMD就近依赖,只有在用到哪个模块的时候再去require;

11、少用float?

①使用float可能会造成兼容性问题,比如在ie6以下,float元素margin加倍问题;②使用float之后会影响左右元素,有可能造成错位问题(float之后都要clear)

解决:可用display、position转化

①无序链接(ul、li),设定li标签属性:display:inline

②div左右结构,比如在右侧要放一个more(更多)来显示更多信息的时候用到了float:right,可以用定位来做。给包裹more的div设定position:relative,然后more这个标签right:0即可。结构更为清晰一点。

18、什么是MVVM框架?

MVVM是Model-View-ViewModel的简写。

MVVM 是 Web 前端一种非常流行的开发模式,利用 MVVM 可以使我们的代码更专注于处理业务逻辑而不是去关心 DOM 操作。目前著名的 MVVM 框架有 vue, avalon, angular 等,这些框架各有千秋,但是实现的思想大致上是相同的:数据绑定 + 视图刷新。跟MVC一样,主要目的是分离视图(View)和模型(Model)。View可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。

在MVVM中,数据是核心,由于VIewModel与View之间的双向绑定,操作了ViewModel中的数据(当然只能是监控属性),就会同步到DOM,我们透过DOM事件监控用户对DOM的改动,也会同步到ViewModel。

<div id="mobile-list"> 
  <h1 v-text="title"></h1> 
  <ul> 
    <li v-for="item in brands"> 
      <b v-text="item.name"></b> 
      <span v-show="showRank">Rank: {{item.rank}}</span> 
    </li> 
  </ul>
</div>
var element = document.querySelector(‘#mobile-list‘);
var vm = new MVVM(element, { 
  ‘title‘ : ‘Mobile List‘,
   ‘showRank‘: true,
   ‘brands‘ : [ 
    {‘name‘: ‘Apple‘, ‘rank‘: 1}, 
    {‘name‘: ‘Galaxy‘, ‘rank‘: 2},
    {‘name‘: ‘OPPO‘, ‘rank‘: 3} 
  ]
});
vm.set(‘title‘, ‘Top 3 Mobile Rank List‘); // => <h1>Top 3 Mobile Rank List</h1>

以上这段如此简洁的代码,就是MVVM框架的一个简单的实现效果。在HTML代码里面,可能会嵌入很多自定义的属性(标记),以此来实现数据的绑定,而且还可以进行一些简单的逻辑处理,比如if和循环等。

react应该也算是MVVM框架,但是与传统的MVVN框架不同的是,react默认数据绑定方式是单向绑定,而vue及angular都是双向绑定;react使用虚拟DOM配合JSX,而vue及angular直接将数据通过属性绑定在真实DOM上的。

MVVM框架的优点:

1、方便测试

在MVC下,Controller基本是无法测试的,里面混杂了个各种逻辑,而且分散在不同的地方。有了MVVM我们就可以测试里面的viewModel,来验证我们的处理结果对不对。

2、便于代码的移植

可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。比如iOS里面有iPhone版本和iPad版本,除了交互展示不一样外,业务逻辑的model是一致的。这样,我们就可以以很小的代价去开发另一个app。

3、独立开发

开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码。

20、使用原生js实现ajax

创建一个 XMLHttpRequest 对象。如果不支持创建该对象的浏览器,则需要创建 ActiveXObject,具体方法如下:

var xmlHttpRequest;
function createXmlHttpRequest(){
  if(window.XMLHttpRequest)//非IE
    xmlHttpRequest = new XMLHttpRequest();
  else if(window.ActiveObject)//IE6+
    xmlHttpRequest = new ActiveObject("Msxml2.XMLHTTP");
  else//IE6-
    xmlHttpRequest = new ActiveObject("Microsoft.XMLHTTP");
}

提交请求的方法:

open(method,url);//分别为提交的方法(GET或者POST)和提交的url
send(content);
onreadystatechange(){
  if(xmlHttpRequest.readyState == 4){
    if(xmlHttpRequest.state == 200){
      //请求成功
    }  
  }else{
    //请求失败
  }
}

1、前端安全方面有没有了解?XSS和CSRF如何攻防?

XSS(Cross Site Scripting)是跨站脚本攻击,为了区分CSS,所以缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。

在网页的一些公共区域(例如,建议提交表单或消息公共板的输入表单)输入一些文本,这些文本被其它用户看到,但这些文本不仅仅是他们要输入的文本,同时还包括一些可以在客户端执行的脚本。如:

"/> <script>alert(document.cookie);</script><!--

在文本框中输入以上代码,然后点击提交,就会把用户的cookie弹出来。

XSS漏洞修复

1.将重要的cookies标记为HTTP ONLY。

2.只允许用户输入我们期望的数据。如年龄框只能输入数字。

3.对数据进行HTTP Encode处理。

4.过滤或者移除特殊的HTML标签。

5.过滤JS事件的标签。

CSRF(Cross-site request forgery)是跨站请求伪造。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。其实就是攻击者盗用了你的身份,以你的名义发送恶意请求。

CSRF攻击的思想

用户浏览并登陆信任网站A;通过验证,在用户处产生X的cookie;用户在没有登出X的时候,浏览危险网站B;B要求访问第三方网站A,发出一个请求;根据这个请求,浏览器使用刚才产生的cookie直接访问A。

一个简单的实例

银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000

危险网站B,它里面有一段HTML的代码如下:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块......

CSRF的防御

1.在表单里增加Hash值,以认证这确实是用户发送的请求,然后在服务器端进行Hash值验证。

2.验证码:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串。

20、是否了解什么前沿的技术、或者你自己有什么技术特长、在哪方便有优势?

以上是关于为啥lua语言中使用全局变量就会造成内存泄漏呢??的主要内容,如果未能解决你的问题,请参考以下文章

垃圾回收机制

为啥 OpenCV Mat 会造成内存泄漏?

在Java程序中这样会不会造成内存泄漏?

前端开发四

内存泄漏

Lua优化:破解全局变量下的使用困局