从架构层面杜绝lua中使用未定义的变量
# 从架构层面杜绝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中使用未定义的变量的更多相关文章
- js 温故而知新 用typeof 来判断一个未定义的变量
一直以为,如果你使用一个未定义的变量,肯定会报错.甚至根本不可能有这种场景. 但仔细想想还是有的,譬如你要判断全局是否存在$变量.或者要为全局暴漏一个全局变量之前,先判断是否有这个变量. typeof ...
- 五十九、SAP中常用预定义系统变量
一.SAP中常用预定义系统变量 内容如下: 二.系统变量定义在结构SYST里,我们打开SE38 三.在代码编辑器输入SYST变量 四.双击SYST,来到这个系统结构,里面有很多系统变量 五.我们随便写 ...
- 关于c调用lua 对‘luaL_newstate()’未定义的引用的问题解决办法
#include <string.h>#include "lua.h"#include "lauxlib.h"#include "lual ...
- 情景剧:C/C++中的未定义行为(undefined behavior)
写在前面 本文尝试以情景剧的方式,轻松.直观地解释C/C++中未定义行为(undefined behavior)的概念.设计动机.优缺点等内容1,希望读者能够通过阅读本文,对undefined beh ...
- C++中的"未定义的行为"
2.1 位运算 位运算的运算对象是整数类型的,并且把运算对象看成是一个二进制位的集合.运算对象可以是带符号也可以是无符号.如果是带符号且值为负,那么位运算如何处理运算对象的符号位依赖于机器.而且此时的 ...
- js在函数中未定义的变量的处理
<html> <head> <script type="text/javascript"> var z=1; function abc(){ x ...
- WPF/UWP 的 Grid 布局竟然有 Bug,还不止一个!了解 Grid 中那些未定义的布局规则
只要你用 XAML 写代码,我敢打赌你一定用各种方式使(nuè)用(dài)过 Grid.不知你有没有在此过程中看到过 Grid 那些匪夷所思的布局结果呢? 本文将带你来看看 Grid 布局中的 Bu ...
- strcasecmp在VS2010中提示未定义标识符
分析: strcasecmp(*,*)是用来比较字符串,定义在string.h头文件中,但是在windows下即使添加string.h头文件,依然会报错. 解决: 添加 #if defined(_MS ...
- javascript中的未定义和未声明
我们在项目中,经常会定义一些变量(很多时候,定义过多的全局变量),当我们调用这些变量的时候,就会发生各种各样的突发状况. 看一个示例: var a; typeof a; typeof b; 很简单的一 ...
随机推荐
- POJ1167 The Buses
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6234 Accepted: 1698 Description A man ...
- XML布局文件于Java代码使用问题
2013-9-21 问题一.不同的XML文件中相同类型的控件id相同,那么将这些不同的布局xml组合在一个大的布局中,如何解决相同id问题 ? 解决办法: 不同的布局文件XML要组合成一个新的大布局, ...
- 标准C程序设计七---111
Linux应用 编程深入 语言编程 标准C程序设计七---经典C11程序设计 以下内容为阅读: <标准C程序设计>(第7版) 作者 ...
- 模块化开发(seajs)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- AC日记——Tree poj 3237
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 9233 Accepted: 2431 Description ...
- 洛谷——P2404 自然数的拆分问题
题目背景 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. 题目描述 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. 输入输出格式 输入格式: 输入:待拆分的自然数n ...
- Linux环境下编译JDK
环境准备 操作系统,ubuntu-14.04.6-desktop-amd64.iso,下载地址:http://59.80.44.100/releases.ubuntu.com/14.04/ubuntu ...
- jsonp _____跨域请求实现
请求如下: $.ajax({ type: "GET", async:false, url: "http://127.0.0.1:8080/Cross-site-reque ...
- Codeforces 471 D MUH and Cube Walls
题目大意 Description 给你一个字符集合,你从其中找出一些字符串出来. 希望你找出来的这些字符串的最长公共前缀*字符串的总个数最大化. Input 第一行给出数字N.N在[2,1000000 ...
- 安装Vmware增强工具
主机: Win7 虚拟机: VMware8.0+Debian6 目标: 离线安装软件包和VMware Tools 在虚拟机上安装完debian6后 1.在vmware的菜单中选择Vm->inst ...