2016-11-22 206 views
0

有人可以告訴我爲什麼我的程序內存不足?我在SDK 1.5.4.1 NodeMCU上使用Lua 5.1.4。這裏是我的代碼什麼導致我的程序使用NodeMCU的內存不足?

wifi.setmode(wifi.STATION) 

wifi.sta.config("asdf","xxx") 

elWiFi =(wifi.sta.getip()) 
if elWiFi ~= nil then 
    print(wifi.sta.getip()) 
end 

if srv~=nil then 
    srv:close() 
end 

srv=net.createServer(net.TCP) 
if srv ~= nil then 
    srv:listen(6969,function(conn) 
     if conn ~= nil then 
     conn:on("receive",function(sck,numbers) 
     if numbers ~= nil then 
      collectgarbage("collect") 
      p = string.find(numbers, "x=") --parses TCP string 
      q = string.find(numbers, "&y") 
      if p ~= nill then 
       if q ~= nil then 
        x = (string.sub(numbers,p+2, q-1)) 
        print("x=" .. x)  -- prints x value 
       end 
      end --p ~= nill 
      p = string.find(numbers, "y=") 
      q = string.find(numbers, "&z") 
      if p ~= nil then 
       if q ~= nil then 
        y = (string.sub(numbers,p+2, q-1)) 
        print("y=" .. y)   --prints y value 
       end 
      end --p ~= nill 
      p = string.find(numbers, "z=") 
      q = string.find(numbers, " H") 
      if p ~= nill then 
       if q ~= nil then 
        z = (string.sub(numbers,p+2, q-1)) 
        --print("z=" .. z) 
       end 
      end-- p ~= nill 
     end --numbers ~= nil 
     conn:close() 
     --conn = nil 

     print(collectgarbage("count")*1024) 
     collectgarbage("collect") 
     --print(collectgarbage("count")*1024) 

     --conn:send("test\n") 

     end) 
     end 
    end) 

end 

我在收集garbare之前和之後分析x和y後打印堆內存。隨着時間的推移它會增加並最終崩潰。

這裏是輸出的樣子

x=-0.003997802734375 
y=-0.0095672607421875 
6744 
6744 
x=-0.0029449462890625 
y=-0.0099945068359375 
7133 
7098 
. 
. 
. 
x=-0.003662109375 
y=-0.00982666015625 
35309 
35275 
x=-0.00311279296875 
y=-0.0097503662109375 
35424 
35389 
E:M 64 
PANIC: unprotected error in call to Lua API (not enough memory) 

ets Jan 8 2013,rst cause:2, boot mode:(3,7) 

load 0x40100000, len 25936, room 16 
tail 0 
chksum 0x5b 
load 0x3ffe8000, len 2268, room 8 
tail 4 
chksum 0xe4 
load 0x3ffe88dc, len 8, room 4 
tail 4 
chksum 0xd9 
csum 0xd9 
„ã ì ƒNì’r‚òn|ä d dld` „ãrÛ$Œ ò „ ìdà 

NodeMCU custom build by frightanic.com 
branch: master 
commit: 7b83bbb2ea134cd85ac9d63108603cc02c4e20f7 
SSL: false 
modules: adc,file,gpio,net,node,ow,pwm,spi,struct,tmr,uart,websocket,wifi 
build built on: 2016-11-15 00:43 
powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32) 
> x=-0.003997802734375 

它之後重新啓動。

感謝您的幫助提前。

回答

0

conn:on("receive")回調,你不能引用conn變量,但sck變量,這裏的原因:

的「連接」事件註冊回調保持一個參考connconn保持參照回調關閉。這創建了一個完美的參考週期。因爲這不能被垃圾收集,所以你的內存泄漏。

此外,您不應該關閉事件回調中的連接。

欲瞭解更多討論,請參閱https://github.com/nodemcu/nodemcu-firmware/issues/1303https://stackoverflow.com/a/37379426/131929

+0

這聽起來很奇怪。參考週期不會阻止Lua收集垃圾。 –

+0

@EgorSkriptunoff,不,但on函數註冊CB在Lua註冊表中,並且當前的網絡代碼沒有將其清除,因爲對象__GC函數沒有被觸發,因爲它持續打開upval,所以mark和sweep doesn不要把它們衝出去。沒有典型的Lua行爲,但會發生這種情況。 – TerryE

+0

@Marcel我不確定我關注。我在'conn:on(「receive」)內沒有引用'conn''我甚至都不使用'sck'。除了'conn:close()',但即使如此,我刪除後,我的程序掛起後,只有3個輸入。 – user3249979

1

在網絡中的這種upval泄漏是一個無賴。避免意外上傳綁定的最簡單方法是提升接收器例程的聲明。像下面這樣。儘管在更經濟的Lua中使用了相同的語法假設,但我還記錄瞭解析器。 (沒有調試,所以我可能會有一個錯字等)

local srv=net.createServer(net.TCP) 
local function receiver(sck,numbers) 
    local p={} 
    for v,n in (numbers or ''):gmatch("([x-z])=(%d+)") do 
    print (("%s=%s"):format(v,n)) 
    p[v]=n+0 
    end 
    -- processReq(p.x, p.y, p.z) 
    print(collectgarbage("count")*1024) 
    collectgarbage("collect") 
    sck:close() 
end 

if svr then 
    srv:listen(6969,function(conn) conn:on("receive",receiver) end) 
end 
相關問題