• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 如何監測apache的內存(也可以說內存具體的使用情況)

    發表于:2007-05-25來源:作者:點擊數: 標簽:
    本人自己安裝了一個第三方插件,在大流量 測試 的情況下發現內存劇烈增長從原來的平均91m增加到600m.我怎樣確定插件和apache如何吃掉內存?現在一點頭緒都沒有,希望高人指點!不勝感謝 haoyufu 回復于:2005-08-03 14:28:11 如何監測內存泄漏 作者 ariesram

    本人自己安裝了一個第三方插件,在大流量測試的情況下發現內存劇烈增長從原來的平均91m增加到600m.我怎樣確定插件和apache如何吃掉內存?現在一點頭緒都沒有,希望高人指點!不勝感謝

     haoyufu 回復于:2005-08-03 14:28:11
    如何監測內存泄漏


    作者
    ariesram
    電子郵件地址
    ariesram@linuxaid.com.cn, 或 ariesram@may10.ca
    本文及本人所有文章均收集在bambi.may10.ca/~ariesram/articles/中。
    本文授權給www.linuxaid.com.cn。

    正文:
    我曾經參與過一個比較大的項目,在這個項目里面,我們沒有一個完全確定的設計文檔,所以程序的實現常常變動。雖然我們有一個比較靈活的框架,但是從程序的角度來講,它使我們的程序非常的混亂。直到發布的日期臨近,我們還沒有一個穩定的可以用來做alpha測試的版本。所以我們必須盡快的刪除掉無用的代碼,讓這個版本足夠的穩定。但是,在這個沒有足夠規范的軟件公司,我們沒有時間也沒有足夠的精力來做邊界測試之類的工作。所以我們只能采用變通的辦法。在軟件中最大的問題就是內存泄漏。因為往往出現這樣的情況,我們在一段代碼中分配了內存,但是卻沒有釋放它。這造成了很大的問題。我們需要一個簡單的解決方案,能夠簡單的編譯進這個項目,在運行的時候,它能夠產生一個沒有被釋放的內存的列表,用這個列表,我們能夠改正程序的錯誤。這就是我們稱之為內存跟蹤的方法。首先,我們需要一種代碼,能夠被加入到源代碼中去,而且這種代碼能夠被重用。代碼重用是一種很重要的特性,能夠節省大量的時間和金錢以及程序員的勞動。另外,我們的這種代碼必須簡單,因為我們當時已經沒有那么多的時間和精力去完全重看一遍所有的代碼來重新編寫以及改正錯誤從而使內存跟蹤能夠起作用。

    好在,我們總能夠找到解決的辦法。首先,我們檢查了代碼,發現所有的代碼都是用new來分配內存,用delete來釋放內存。那么,我們能夠用一個全程替換,來替換掉所有的new和delete操作符嗎?不能。因為代碼的規模太大了,那樣做除了浪費時間沒有別的任何好處。好在我們的源代碼是用C++來寫成的,所以,這意味著沒有必要替換掉所有的new和delete,而只用重載這兩個操作符。對了,值用重載這兩個操作符,我們就能在分配和釋放內存之前做點什么。這是一個絕對的好消息。我們也知道該如何去做。因為,MFC也是這么做的。我們需要做的是:跟蹤所有的內存分配和交互引用以及內存釋放。我們的源代碼使用Visual C++寫成,當然這種解決方法也可以很輕松的使用在別的C++代碼里面。要做的第一件事情是重載new和delete操作符,它們將會在所有的代碼中被使用到。我們在stdafx.h中,加入:
          #ifdef _DEBUG
          inline void * __cdecl operator new(unsigned int size, 
                                             const char *file, int line)
          {
          };

          inline void __cdecl operator delete(void *p)
          {
          };
          #endif
    這樣,我們就重載了new和delete操作符。我們用$ifdef和#endif來包住這兩個重載操作符,這樣,這兩個操作符就不會在發布版本中出現??匆豢催@段代碼,會發現,new操作符有三個參數,它們是,分配的內存大小,出現的文件名,和行號。這對于尋找內存泄漏是必需的和重要的。否則,就會需要很多時間去尋找它們出現的確切地方。加入了這段代碼,我們的調用new()的代碼仍然是指向只接受一個參數的new操作符,而不是這個接受三個參數的操作符。另外,我們也不想記錄所有的new操作符的語句去包含__FILE__和__LINE__參數。我們需要做的是自動的讓所有的接受一個參數的new操作符調用接受三個參數的new操作符。這一點可以用一點點小的技巧去做,例如下面的這一段宏定義,
          #ifdef _DEBUG
          #define DEBUG_NEW new(__FILE__, __LINE__)
          #else
          #define DEBUG_NEW new
          #endif
          #define new DEBUG_NEW
    現在我們所有的接受一個參數的new操作符都成為了接受三個參數的new操作符號,__FILE__和__LINE__被預編譯器自動的插入到其中了。然后,就是作實際的跟蹤了。我們需要加入一些例程到我們的重載的函數中去,讓它們能夠完成分配內存和釋放內存的工作。這樣來做, #ifdef _DEBUG
          inline void * __cdecl operator new(unsigned int size,
                                             const char *file, int line)
          {
    void *ptr = (void *)malloc(size);
    AddTrack((DWORD)ptr, size, file, line);
    return(ptr);
          };
          inline void __cdecl operator delete(void *p)
          {
    RemoveTrack((DWORD)p);
    free(p);
          };
          #endif
    另外,還需要用相同的方法來重載new[]和delete[]操作符。這里就省略掉它們了。
    最后,我們需要提供一套函數AddTrack()和RemoveTrack()。我用STL來維護存儲內存分配記錄的連接表。
    這兩個函數如下:
          typedef struct {
    DWORD address;
    DWORD size;
    char file[64];
    DWORD line;
          } ALLOC_INFO;

          typedef list<ALLOC_INFO*> AllocList;

          AllocList *allocList;

          void AddTrack(DWORD addr, DWORD asize, const char *fname, DWORD lnum)
          {
    ALLOC_INFO *info;

    if(!allocList) {
    allocList = new(AllocList);
    }

    info = new(ALLOC_INFO);
    info->address = addr;
    strncpy(info->file, fname, 63);
    info->line = lnum;
    info->size = asize;
    allocList->insert(allocList->begin(), info);
          };

          void RemoveTrack(DWORD addr)
          {
    AllocList::iterator i;

    if(!allocList)
    return;
    for(i = allocList->begin(); i != allocList->end(); i++)
    {
    if((*i)->address == addr)
    {
    allocList->remove((*i));
    break;
    }
    }
          };
    現在,在我們的程序退出之前,allocList存儲了沒有被釋放的內存分配。為了看到它們是什么和在哪里被分配的,我們需要打印出allocList中的數據。我使用了Visual C++中的Output窗口來做這件事情。
          void DumpUnfreed()
          {
    AllocList::iterator i;
    DWORD totalSize = 0;
    char buf[1024];

    if(!allocList)
    return;

    for(i = allocList->begin(); i != allocList->end(); i++) {
    sprintf(buf, "%-50s: LINE %d, ADDRESS %d %d unfreed ",
    (*i)->file, (*i)->line, (*i)->address, (*i)->size);
    OutputDebugString(buf);
    totalSize += (*i)->size;
    }
    sprintf(buf, "----------------------------------------------------------- ");
    OutputDebugString(buf);
    sprintf(buf, "Total Unfreed: %d bytes ", totalSize);
    OutputDebugString(buf);
          };
    現在我們就有了一個可以重用的代碼,用來監測跟蹤所有的內存泄漏了。這段代碼可以用來加入到所有的項目中去。雖然它不會讓你的程序看起來更好,但是起碼它能夠幫助你檢查錯誤,讓程序更加的穩定。

     waterlesssea 回復于:2005-08-05 18:02:02
    重載的new和delete能正確調用相應的構造函數和析構函數嗎?
    不解...

     haoyufu 回復于:2005-08-06 14:02:35
    完全可以

    說說具體的

     haoyufu 回復于:2005-08-09 13:04:01
    說說你的具體情況

     jsean 回復于:2005-08-12 11:15:58
    如果對類的構造函數進行了重載,這樣作也可以嗎?

    并且很多new并不是只傳一個size參數的,你這樣作只是替換最終的new(size)?還是對程序中出現的所有的new都起作用?

     shdx 回復于:2005-08-12 18:39:33
    上海服務器租用、托管(上海電信機房)、虛擬主機、域名注冊、企業郵局、DDN專線等。上海正規IDC公司——上海電梟網絡科技有限公司
    上海電梟網絡提供以主機托管,主機租用的全方位互聯網服務!提供諸如、電影下載、音樂網站、網絡游戲、視頻聊天室、網絡社區、企業郵局、虛擬主機等多種服務器的租用、托管,技術支持等等……
    [img:03813d0a13]http://wpa.qq.com/pa?p=1:469613235:11[/img:03813d0a13][url=http://wpa.qq.com/msgrd?V=1&Uin=469613235&Site=yk.jhisp.com/bbs/&Menu=yes]點擊這里即時與我QQ聯系[/url]
    聯系方式:
    客服QQ:469613235 或 86221118              MSN/Email:shdx@datasupermarket.com
    電話:021-58627258轉20  湯立鋒(先生)    傳真:021-58627238
    地址:上海外高橋季景路259弄17號602室  
    更多詳情請登陸www.datasupermarket.com上海電梟網絡科技有限公司網站 www.shujuchaoshi.com數據超市

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>