# 从架构层面杜绝lua中使用未定义的变量

标签(空格分隔): lua

---

lua中有一个很坑的地方:
1.就是如果一个变量拼写错误,会自动的认为你定义了一个值为nil的全局变量.
2.如果在function中定义一个局部变量,忘记了local,则会默认为是定义成为了一个全局变量.

为了防止这种问题,我今天想到一个解决方案.
可以达到以下效果:
1.在function中使用一个未定义的变量时则报错.
2.在function中定义全局变量则报错,即全局变量中能够在全局空间中定义.

具体做法如下:
在代码初始化的时候,重写_G的__newindex,这个是在往_G中加新东西的时候会调用的,即定义全局变量的时候会调用.
首先我们用一个table来记录定义了那些全局变量,这样做的目的是,我们之后可以在使用全局变量的时候判断时候已经定义了该全局变量.所以我们还应该重写__index,这个__index是在使用表中的内容会调用的.
所以有了如下代码:
```
local tbDefineValue = {}

setmetatable(_G, {
__index = function(tb, key)
if not tbDefineValue[key] then
error(string.format("找不到全局变量:%s", key))
return nil
end
rawget(tab, key)
end,
_newindex = function(tb, key, value)
tbDefineValue[key] = true
rawset(tb, key, value)
end
}

)
```
我们把这段代码放到一个全局空间的最先require的文件里面,做初始化.
这样之后我们每定义一个全局对象都会记录.
另外,很关键的一点是:这个代码会在初始化的调用.所以之后定义的全局变量会记录,使用全局变量会检查时候有该全局变量,如果有就返回,否则报错;

然后在程序运行过程中,我们需要有一个init函数来处理.
在运行过程中,我们需要禁止创建全局变量,只能够改变现有全局变量的值或者使用现有的全局变量.
所以我们需要禁止_G的__newindex的时候去增加全局变量.
所以我们有一个```init()```函数,用于设置_G只读.
代码如下:
```
function init()
setmetatable(_G, {
__newindex = function(tb, key, value)
do return end
-- tbDefineValue[key] = true
-- rawset(tb, key, value)
end,
})
end
```
大功告成.
以下是测试用例.
```
local tbDefineValue = {}
setmetatable(_G, {
__index = function(tb, key)
if not tbDefineValue[key] then
error(string.format("can not find global:%s", key))
return nil
end
rawget(tab, key)
end,
_newindex = function(tb, key, value)
tbDefineValue[key] = true
rawset(tb, key, value)
end
}
)

function disableWrite_G()
setmetatable(_G, {
__newindex = function(tb, key, value)
error(string.format("can not define global value:%s in local space", key))
do return end
end,
})
end

c = 12
print(c)

function test2()
d = 12
c = 13
end

function test3()
print(c)
if a == 12 then
print(123)
end
end

function start()
disableWrite_G()
test2()
test3()
end

start()
```
输出结果是
```
D:\Binaries-LuaDist-batteries-0.9.8-Windows-x86\bin\lua.exe: .\test.lua:20: can not define global value锛歞 in local space
stack traceback:
[C]: in function 'error'
.\test.lua:20: in function <.\test.lua:19>
.\test.lua:30: in function 'test2'
.\test.lua:43: in function 'start'
.\test.lua:47: in main chunk
[C]: ?

```

从架构层面杜绝lua中使用未定义的变量的更多相关文章

  1. js 温故而知新 用typeof 来判断一个未定义的变量

    一直以为,如果你使用一个未定义的变量,肯定会报错.甚至根本不可能有这种场景. 但仔细想想还是有的,譬如你要判断全局是否存在$变量.或者要为全局暴漏一个全局变量之前,先判断是否有这个变量. typeof ...

  2. 五十九、SAP中常用预定义系统变量

    一.SAP中常用预定义系统变量 内容如下: 二.系统变量定义在结构SYST里,我们打开SE38 三.在代码编辑器输入SYST变量 四.双击SYST,来到这个系统结构,里面有很多系统变量 五.我们随便写 ...

  3. 关于c调用lua 对‘luaL_newstate()’未定义的引用的问题解决办法

    #include <string.h>#include "lua.h"#include "lauxlib.h"#include "lual ...

  4. 情景剧:C/C++中的未定义行为(undefined behavior)

    写在前面 本文尝试以情景剧的方式,轻松.直观地解释C/C++中未定义行为(undefined behavior)的概念.设计动机.优缺点等内容1,希望读者能够通过阅读本文,对undefined beh ...

  5. C++中的"未定义的行为"

    2.1 位运算 位运算的运算对象是整数类型的,并且把运算对象看成是一个二进制位的集合.运算对象可以是带符号也可以是无符号.如果是带符号且值为负,那么位运算如何处理运算对象的符号位依赖于机器.而且此时的 ...

  6. js在函数中未定义的变量的处理

    <html> <head> <script type="text/javascript"> var z=1; function abc(){ x ...

  7. WPF/UWP 的 Grid 布局竟然有 Bug,还不止一个!了解 Grid 中那些未定义的布局规则

    只要你用 XAML 写代码,我敢打赌你一定用各种方式使(nuè)用(dài)过 Grid.不知你有没有在此过程中看到过 Grid 那些匪夷所思的布局结果呢? 本文将带你来看看 Grid 布局中的 Bu ...

  8. strcasecmp在VS2010中提示未定义标识符

    分析: strcasecmp(*,*)是用来比较字符串,定义在string.h头文件中,但是在windows下即使添加string.h头文件,依然会报错. 解决: 添加 #if defined(_MS ...

  9. javascript中的未定义和未声明

    我们在项目中,经常会定义一些变量(很多时候,定义过多的全局变量),当我们调用这些变量的时候,就会发生各种各样的突发状况. 看一个示例: var a; typeof a; typeof b; 很简单的一 ...

随机推荐

  1. hdu 4372 Count the Buildings 轮换斯特林数

    题目大意 n栋楼有n个不同的高度 现在限制从前面看有F个点,后面看有B个点 分析 最高那栋楼哪都可以看到 剩下的可以最高那栋楼前面分出F-1个组 后面分出B-1个组 每个组的权值定义为组内最高楼的高度 ...

  2. poj 4438 Hunters

    Hunters Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  3. 【NOIP2016练习】T3 tree (树形DP)

    题意:一棵有N个结点的树,每个节点上有权值c[i] 需要选出若干结点,对于任意结点他的所有祖先都被选取且选取总个数不能超过lim 在此前提下使权值和最大 n,lim<=3000 思路:WA了1次 ...

  4. 标准C程序设计七---60

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...

  5. [leetcode]84.Largest Rectangle in Histogram ,O(n)解法剖析

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  6. 使用vue-element-admin框架开发时遇到的跨域问题

    之前 使用js和jquery开发时也碰到过接口请求时的跨域问题, 但是在使用vue-element-admin开发也碰到这个问题,而且不能使用之前的方法解决,查过不少资料,找到一个很好的方法解决了这个 ...

  7. iNeuOS云操作系统,.NET Core全系打造

    iNeuOS云操作系统,.NET Core全系打造 目录 一.演示地址... 2 二.技术体系... 2 三.iNeuOS整体介绍... 2 四.iNeuView概述... 3 五.iNeuView操 ...

  8. C# 根据生日获取年龄

    C# 根据生日获取年龄 根据生日计算出准确的年龄,不等于0时,返回的是岁,等于0时,返回的是天(以‘-’来区分) public static string GetAgeByBirth(string B ...

  9. Springboot构建问题集

    最近在搭建框架时遇到很多细节问题,时间久了就很容易忘记,在此记录一下. 1.问题:Warning:java: 来自注释处理程序 'org.antlr.v4.runtime.misc.NullUsage ...

  10. 老毛桃winpe优盘启动系统个性修改全攻略.(全)

    博主从05年开始接触计算机,不能说是高手也算个老菜了,当时装系统还是用蕃茄花园的光盘安装系统,后来在学校管理机房,哪台电脑坏了就硬盘对拷. 时到今日,重启系统的方法五花八门,其中使用最广的莫过于PE优 ...