这是否是lua变量作用域问题(以及如何解决)?

非常奇怪的错误,显示一个对象是空的。

一个人会认为,如果 pbs:HasNext()true,意味着 pbs 一定不是 nil

然而,HTMLEntityCodec:DecodeCharacter 的第一行打印了 nil

function HTMLEntityCodec:DecodeCharacter(pbs)
    print(pbs)
    ...

完整文件如下,从 1800 多行被削减到 110 行,以便于 SO 用户可以更清晰地获取上下文。但是这种削减会将代码中的所有逻辑削减掉,所以不要被搞混了。

#!/usr/bin/env lua

function Inherits( baseClass )
    local new_class = {}
    local class_mt = { __index = new_class }

    function new_class:create()
        local newinst = {}
        setmetatable( newinst, class_mt )
        return newinst
    end

    if baseClass then
        setmetatable( new_class, { __index = baseClass } )
    end

    return new_class
end

-------------------------------------------
-- PushbackString
-------------------------------------------
PushbackString = Inherits({})

function PushbackString:Init(input)
    self.input = input
    self.pushback = nil
    self.temp = nil
    self.index = 0
    self.mark = 0
end

-- 标记当前索引,这样客户端可以在需要时重置到它。
function PushbackString:HasNext()
    return true
end

function PushbackString:Mark ()
    self.temp = self.pushback
    self.mark = self.index
end

BaseCodec = Inherits({})

function BaseCodec:Decode(input)
    local buff = ''
    local pbs = PushbackString:create()

    pbs:Init(input)

    while pbs:HasNext() do
        local char = self.DecodeCharacter(pbs)
        if char ~= nil then
            buff = buff .. char
        else
            buff = buff .. pbs:Next()
        end
    end
    return buff
end

HTMLEntityCodec = Inherits(BaseCodec)
-- HTMLEntityCodec.classname = ('HTMLEntityCodec')

function HTMLEntityCodec:DecodeCharacter(pbs)
    print(pbs)
    pbs:Mark()
end

DefaultEncoder = Inherits({})

function DefaultEncoder:Init(codecs)
    self.html_codec = HTMLEntityCodec:create()
end

function DefaultEncoder:TestInput(input , strict)
    print ("\n----------------8<----------------8<----------------\n")
    print ("Input:\t" .. input)
    -- 默认值
    if strict == nil then strict = true end

    -- 无事可做
    if input == nil then return nil end

    local working = input
    local codecs_found = {}
    local found_count = 0
    local clean = false

    while not clean do
        clean = true
        old = working
        working = self.html_codec:Decode( working )
        if old ~= working then
            print ("Warning:\tINTRUSION DETECTED")
        end
    end

    print ("Output:\t".. working)
    return working
end

local default_encoder = DefaultEncoder:create()
default_encoder:Init()
default_encoder:TestInput("%25", true)

----------8<-----------8<--------------8<----------------

文件结束。

控制台输出:

tzury@1005:~/devel/lua$ lua problem.lua

----------------8<----------------8<----------------

Input:  %25
nil
lua: problem.lua:70: attempt to index local 'pbs' (a nil value)
stack traceback:
        problem.lua:70: in function 'DecodeCharacter'
        problem.lua:54: in function 'Decode'
        problem.lua:96: in function 'TestInput'
        problem.lua:109: in main chunk
        [C]: ?

原文链接 https://stackoverflow.com/questions/7791636

点赞
stackoverflow用户221509
stackoverflow用户221509

在你的代码中,崩溃发生在这一行:

local char = self.DecodeCharacter(pbs)

问题在于你使用了错误数量的参数调用 DecodeCharacter 函数。

解决方案:像这样调用它(注意冒号):

local char = self:DecodeCharacter(pbs)

解释

当你使用冒号(:)在 Lua 中定义函数时,你使用的是语法糖,它隐藏了一个名为 self 的隐含第一个参数。类似这样的定义:

function HTMLEntityCodec:DecodeCharacter(pbs) ... end

实际上被“翻译”成了这个样子:

HTMLEntityCodec.DecodeCharacter = function (self, pbs) ... end

当你调用函数时,你需要手动传递 self 参数,或使用冒号调用来自动传递它。在你的代码中(self.DecodeCharacter(pbs)),你传递了 pbs,这最终在 HTMLEntityCodec.DecodeCharacter 中变成了 self,而 pbs 变成了 nil。以下两个调用是相等的,并应该解决这个问题:

local char = self.DecodeCharacter(self, pbs)
local char = self:DecodeCharacter(pbs)
2011-10-17 10:54:59