这是一个可变范围问题(如何解决)?

时间:2011-10-17 09:14:45

标签: lua

一个非常奇怪的错误,显示一个对象为零。

主题中的代码是

while pbs:HasNext() do
    local char = self.DecodeCharacter(pbs)
    ...

有人会认为,如果pbs:HasNext()true,则表示pbs nil,无论如何。

然而,打印(pbs) - 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

-- Mark the current index, so the client can reset() to it if need be.        
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)
    -- default value
    if strict == nil then strict = true end

    -- nothing to do
    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]: ?

1 个答案:

答案 0 :(得分:4)

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

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最终为self HTMLEntityCodec.DecodeCharacterpbs最终为nil。以下两个电话都是等效的,应该可以解决问题:

local char = self.DecodeCharacter(self, pbs)
local char = self:DecodeCharacter(pbs)