簡體   English   中英

VBScript Out of Memory錯誤

[英]VBScript Out Of Memory Error

我有一個由第三方公司建立的經典ASP CRM。 目前,我可以訪問源代碼,並且可以進行任何更改。

隨機地全天,通常在用戶長時間使用之后,我的大多數頁面都開始出現Out of Memory錯誤。

構建應用程序的方式是,所有頁面和腳本都從Global.asp文件中提取核心功能。 在該文件中也嵌入了其他全局文件,但顯示的錯誤顯示

記不清

WhateverScriptYouTriedToRun.asp第0行

第0行是global.asp文件的include。 一旦發生錯誤,在一段未指定的時間之后,錯誤發生在一段時間內消退,但隨后又開始再次發生。 關於應用程序的編寫方式,它使用的功能,以及我已經完成的“診斷” - 它似乎是一個常見的使用函數,它隱藏了記錄集之類的數據或者那種性質的東西,然后沒有正確地釋放它。 然后其他用戶嘗試使用相同的功能,最終它只是填滿導致錯誤。 我有效清除錯誤的唯一方法是實際重啟IIS,回收應用程序池,然后重新啟動SQL Server服務。

不用說,我和我的用戶都很生氣....

由於實際的錯誤消息顯示為第0行,我無法查明錯誤 - 但是從那里我不知道在20K行代碼中它可能會掛起。 關於如何隔離或至少指出我正確的方向以開始清理它的任何想法或想法? 有沒有辦法讓我增加VBScript的“內存”大小? 我知道有一個限制但它設置為... 512K你可以增加到1GB?

以下是我嘗試過的事情:

  1. 將SQL內聯語句刪除到視圖中
  2. 通過幾百個腳本並確保每個OpenConnection和OpenRecordSet后面都有一個適當的Close。
  3. 瀏覽全局文件並注釋掉任何大型SQL語句,例如ApplicationLog(將執行的查詢寫入表中的函數)。
  4. 一些較小的腳本編輯。

常見的內存泄漏

你說你正在關閉所有好的記錄集和連接。

但是你要刪除對象嗎?

例如:

Set adoCon = new
Set rsCommon = new

'Do query stuff

'You do this:
rsCommon.close
adocon.close

'But do you do this?
Set adoCon = nothing
Set rsCommon = nothing

經典ASP中沒有垃圾收集,因此任何未銷毀的對象都將保留在內存中。

此外,確保在每個分支中運行關閉/未關閉。 例如:

adocon.open
rscommon.open etc

'Sql query
myData = rscommon("condition")

if(myData) then
  response.write("ok")
else
  response.redirect("error.asp")
end if

'close
rsCommon.close
adocon.close
Set adoCon = nothing
Set rsCommon = nothing

在重定向之前沒有任何東西被關閉/銷毀,所以它只會在某些時候清空內存,因為並非所有邏輯分支都能導致正確的內存清除。

更好的設計

還不幸的是,這聽起來像網站設計不好。 我總是將我的經典ASP構建為:

<%
    Option Explicit

    'Declare all vars
    Dim this
    Dim that

    'Open connections
    Set adoCon...
    adocon.open()

    'Fetch required data
    rscommon.open strSQL, adoCon
        this = rsCommon.getRows()
    rsCommon.close

    'Fetch something else
    rscommon.open strSQL, adoCon
        that = rsCommon.getRows()
    rsCommon.close

    'Close connections and drop objects
    adoCon.close
    set adoCon = nothing
    set rscommon = nothing

    'Process redirects
    if(condition) then
        response.redirect(url)
    end if
%>
<html>
<body>

<%
    'Use data
    for(i = 0 to ubound(this,2)
        response.write(this(0, i) & " " & this(1, i) & "<br />")
    next
%>

</body>

</html>

希望其中一些有所幫助。

你有沒有看過使用內存監控工具來查看內存碎片發生了多少? 我猜測可能的原因是某個大小的對象正在嘗試創建,但內存中沒有足夠的空間將其存儲為一個連續的塊。 想象一下,需要空間來存儲一個占用100 MB的對象,而且可能有幾百兆的空閑,最大的連續塊是90MB然后這不適合。


調試診斷工具v1.1將是Bernard的文章可以幫助理解如何使用該工具的工具。

另一個想法是代碼中有多少字符串連接的問題? 我記得我以前工作的地方遇到了很多字符串連接操作的問題,這些操作會占用內存,這可能是另一個需要考慮的想法。


是的,我可以看到你看到它的前幾次在那種數字上有些震撼,但是如果你明白代碼在做什么,那么為什么這么多空間有時會被保留下來可能是有意義的。


我沒有專門使用該調試工具,但我確實有一個工具在掛起頁面時拍攝了內存快照,所以我無法判斷該工具是否存在性能影響。 在我的案例中,我在2004年使用了類似的工具,因此我已經研究了這類問題已有幾年了。

只是把它放在這里,但這個問題需要很長時間才能解決。 以下是我們所做的細分:

  1. 我們采用了所有內聯SQL並創建了SQL視圖,現在每個SELECT語句都首先使用VIEW處理。

  2. 我采用了每一個SQL INSERT和UPDATE(盡可能多的不破壞系統)並將它們放入存儲過程中。

    #2是真正發揮最大作用的一個項目

  3. 經歷了數千個腳本,並確保變量得到妥善處理,並且所有數據庫打開連接都通過關閉連接正確地跟蹤,並且與打開/關閉RecordSet相同。

  4. 其中一個緩慢的殺手就是:

    ID = Request.QueryString(“ID)

在頁面頂部。 在重定向或關閉頁面之前,始終存在:

Set ID = Nothing 

或徹底刪除推斷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM