如何進行php內(nèi)存調(diào)試

如何進行php內(nèi)存調(diào)試?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

主要從事網(wǎng)頁設計、PC網(wǎng)站建設(電腦版網(wǎng)站建設)、wap網(wǎng)站建設(手機版網(wǎng)站建設)、響應式網(wǎng)站建設、程序開發(fā)、微網(wǎng)站、小程序設計等,憑借多年來在互聯(lián)網(wǎng)的打拼,我們在互聯(lián)網(wǎng)網(wǎng)站建設行業(yè)積累了豐富的成都網(wǎng)站設計、網(wǎng)站建設、網(wǎng)絡營銷經(jīng)驗,集策劃、開發(fā)、設計、營銷、管理等多方位專業(yè)化運作于一體,具備承接不同規(guī)模與類型的建設項目的能力。

                                               

內(nèi)存調(diào)試

本章是有關PHP源代碼的內(nèi)存調(diào)試的簡要介紹。 這不是一門完整的課程:內(nèi)存調(diào)試并不難, 但是你需要一些它的使用經(jīng)驗,大量的練習可能是你在設計任何C編寫的代碼時都必須要做的事情。我們將在這里介紹一個非常著名的內(nèi)存調(diào)試器: valgrind; 以及如何將其與PHP一起使用來調(diào)試內(nèi)存問題。

Valgrind簡介

Valgrind是許多Unix環(huán)境下使用的知名工具,可以在任何C/C++編寫的軟件中調(diào)試許多常見的內(nèi)存問題。 Valgrind 是有關內(nèi)存調(diào)試的多功能前端工具。最常用的底層工具稱為 “memcheck”。它的工作方式是用自己的堆分配替換每個libc的堆分配,并跟蹤你對它們所做的事情。你可能還會對 “massif” 感興趣: 它是一個內(nèi)存跟蹤器,對于了解程序的常規(guī)堆內(nèi)存使用情況非常有用。

注意

你應該閱讀Valgrind文檔,以進一步了解。 它寫得很好,帶有一些典型的例子。

為了進行內(nèi)存分配替換,你需要通過 valgrind 運行要分析的程序(此處為PHP),也就是啟動 valgrind 二進制文件。

當 valgrind 替換并跟蹤所有 libc 的堆分配時,它往往會大大降低調(diào)試程序的速度。對于PHP,你會注意到它。盡管 PHP 的速度下降并不那么劇烈,但是仍然可以清楚地感覺到;如果你注意到它,不用擔心,這是正常的。

Valgrind 不是你可能會使用的唯一工具,但是是最常用的工具。還有其他工具,例如 Dr.Memory、LeakSanitizer、Electric Fence、AddressSanitizer。

在開始之前

以下是在存儲器調(diào)試方面具有良好經(jīng)驗并減輕發(fā)現(xiàn)缺陷并減少調(diào)試時間的機會所需的步驟:

-您應始終使用PHP的調(diào)試版本。嘗試調(diào)試生產(chǎn)版本中的內(nèi)存是無關緊要的。
-您應該始終在 USE_ZEND_ALLOC = 0 環(huán)境下啟動調(diào)試器。您可能已經(jīng)在Zend Memory Manager章節(jié)中了解到,此環(huán)境var會在當前進程啟動時禁用ZendMM。強烈建議在啟動內(nèi)存調(diào)試器時這樣做。完全繞過ZendMM有助于了解valgrind生成的跟蹤。
-強烈建議在環(huán)境 ZEND_DONT_UNLOAD_MODULES = 1 下啟動內(nèi)存調(diào)試器。這樣可以防止PHP在過程結(jié)束時卸載擴展程序的.so文件。這是為了獲得更好的valgrind報告跟蹤;如果在valgrind將要顯示其錯誤時PHP將卸載擴展名,則稍后將不完整,因為從中獲取信息的文件不再是進程內(nèi)存映像的一部分。
-您可能需要一些抑制措施。當您告訴PHP在過程結(jié)束時不要卸載其擴展名時,可能會在valgrind輸出中給您誤報。將檢查PHP擴展是否泄漏,如果您在平臺上誤報,則可以使用抑制功能將其關閉像這樣。可以根據(jù)這樣的示例隨意編寫自己的文件。
-與Zend Memory Manager相比,Valgrind顯然是更好的工具,可以查找泄漏和其他與內(nèi)存相關的問題。您應該始終在代碼上運行valgrind,這實際上是每個C程序員都必須執(zhí)行的步驟。無論是因為崩潰而想要找到并調(diào)試它,還是作為看起來好像沒有任何壞處的高質(zhì)量工具來運行它,valgrind都是這種工具,它可以指出隱藏的瑕疵,準備好將其吹拂一次或以后。即使您認為代碼似乎一切都很好,也可以使用它:您可能會感到驚訝。

Warning

您**必須在程序上使用valgrind(或任何內(nèi)存調(diào)試器)。對于每個強大的C程序,要不調(diào)試內(nèi)存就不可能100%充滿信心。內(nèi)存錯誤會導致有害的安全問題,并且程序崩潰通常取決于許多參數(shù),通常是隨機的。

內(nèi)存泄漏檢測示例

入門

Valgrind是一個完整的堆內(nèi)存調(diào)試器。它還可以調(diào)試過程內(nèi)存映射和功能堆棧。請在其文檔中獲取更多信息。

讓我們?nèi)z測動態(tài)內(nèi)存泄漏,并嘗試一個簡單的,最常見的泄漏:

PHP_RINIT_FUNCTION(pib)
{
    void *foo = emalloc(128);
}

上面的代碼每次請求都會泄漏128字節(jié),因為它沒有與此類緩沖區(qū)有關的efree()相關調(diào)用。由于它是對emalloc()的調(diào)用,因此會通過Zend Memory Manager,因此稍后會警告我們就像我們在ZendMM章節(jié)中看到的那樣。我們還要看看valgrind是否可以注意到泄漏:

> ZEND_DONT_UNLOAD_MODULES=1 USE_ZEND_ALLOC=0 valgrind --leak-check=full --suppressions=/path/to/suppression
--show-reachable=yes --track-origins=yes ~/myphp/bin/php -dextension=pib.so /tmp/foo.php

我們使用valgrind啟動PHP-CLI進程。我們在這里假設一個名為“ pib”的擴展名。這是輸出:

==28104== 128 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28104==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28104==    by 0xA3701E: __zend_malloc (zend_alloc.c:2820)
==28104==    by 0xA362E7: _emalloc (zend_alloc.c:2413)
==28104==    by 0xE896F99: zm_activate_pib (pib.c:1880)
==28104==    by 0xA79F1B: zend_activate_modules (zend_API.c:2537)
==28104==    by 0x9D31D3: php_request_startup (main.c:1673)
==28104==    by 0xB5909A: do_cli (php_cli.c:964)
==28104==    by 0xB5A423: main (php_cli.c:1381)

==28104== LEAK SUMMARY:
==28104==    definitely lost: 128 bytes in 1 blocks
==28104==    indirectly lost: 0 bytes in 0 blocks
==28104==    possibly lost: 0 bytes in 0 blocks
==28104==    still reachable: 0 bytes in 0 blocks
==28104==    suppressed: 7,883 bytes in 40 blocks

在我們看來,“絕對失落”是我們必須關注的。

Note

有關memcheck輸出的不同字段的詳細信息,請查看。

Note

我們使用USE_ZEND_ALLOC = 0禁用并完全繞過Zend Memory Manager。對其API的每次調(diào)用(例如emalloc())將直接導致libc調(diào)用,就像我們在calgrind輸出堆棧幀上可以看到的那樣。

Valgrind抓住了我們的漏洞。

很容易,現(xiàn)在我們可以使用持久分配(也就是繞過ZendMM并使用傳統(tǒng)libc的動態(tài)內(nèi)存分配)來產(chǎn)生泄漏。走:

PHP_RINIT_FUNCTION(pib)
{
    void *foo = malloc(128);
}

這是報告:

==28758==    128 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28758==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28758==    by 0xE896F82: zm_activate_pib (pib.c:1880)
==28758==    by 0xA79F1B: zend_activate_modules (zend_API.c:2537)
==28758==    by 0x9D31D3: php_request_startup (main.c:1673)
==28758==    by 0xB5909A: do_cli (php_cli.c:964)
==28758==    by 0xB5A423: main (php_cli.c:1381)

也抓到了。

Note

Valgrind確實可以捕獲所有內(nèi)容。巨大的進程內(nèi)存映射中某個地方的每一個被遺忘的小字節(jié)都會被valgrind的眼睛報告。您無法通過。

更復雜的用例

這是一個更復雜的設置。您可以在下面的代碼中發(fā)現(xiàn)泄漏嗎?

static zend_array ar;

PHP_MINIT_FUNCTION(pib)
{
    zend_string *str;
    zval string;

    str = zend_string_init("yo", strlen("yo"), 1);
    ZVAL_STR(&string, str);

    zend_hash_init(&ar, 8, NULL, ZVAL_PTR_DTOR, 1);
    zend_hash_next_index_insert(&ar, &string);
}

這里有兩個泄漏。首先,我們分配一個zend_string,但我們沒有釋放它。其次,我們分配一個新的zend_hash,但是我們也不釋放它。讓我們用valgrind啟動它,然后查看結(jié)果:

==31316== 296 (264 direct, 32 indirect) bytes in 1 blocks are definitely lost in loss record 1 of 2
==32006==    by 0xA3701E: __zend_malloc (zend_alloc.c:2820)
==32006==    by 0xA814B2: zend_hash_real_init_ex (zend_hash.c:133)
==32006==    by 0xA816D2: zend_hash_check_init (zend_hash.c:161)
==32006==    by 0xA83552: _zend_hash_index_add_or_update_i (zend_hash.c:714)
==32006==    by 0xA83D58: _zend_hash_next_index_insert (zend_hash.c:841)
==32006==    by 0xE896AF4: zm_startup_pib (pib.c:1781)
==32006==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==32006==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==32006==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==32006==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)

==31316== 32 bytes in 1 blocks are indirectly lost in loss record 2 of 2
==31316==    by 0xA3701E: __zend_malloc (zend_alloc.c:2820)
==31316==    by 0xE880B0D: zend_string_alloc (zend_string.h:122)
==31316==    by 0xE880B76: zend_string_init (zend_string.h:158)
==31316==    by 0xE896F9D: zm_activate_pib (pib.c:1781)
==31316==    by 0xA79F1B: zend_activate_modules (zend_API.c:2537)
==31316==    by 0x9D31D3: php_request_startup (main.c:1673)
==31316==    by 0xB5909A: do_cli (php_cli.c:964)
==31316==    by 0xB5A423: main (php_cli.c:1381)

==31316== LEAK SUMMARY:
==31316== definitely lost: 328 bytes in 2 blocks

如預期的那樣,兩個泄漏都被報告。如您所見,valgrind是準確的,它將您的眼睛放在需要的地方。

現(xiàn)在修復它們:

PHP_MSHUTDOWN_FUNCTION(pib)
{
    zend_hash_destroy(&ar);
}

我們在PHP程序結(jié)束時在MSHUTDOWN中銷毀了持久數(shù)組。創(chuàng)建它時,我們將其作為析構(gòu)函數(shù)傳遞給ZVAL_PTR_DTOR,它將在插入的所有項目上運行該回調(diào)。這是zval的析構(gòu)函數(shù),它將破壞zval分析它們的內(nèi)容。對于IS_STRING類型,析構(gòu)函數(shù)將釋放zend_string并在必要時釋放它。做完了

Note

如您所見,PHP-像任何C語言強程序一樣-充滿了嵌套的指針。zend_string封裝在zval中,其本身是zend_array的一部分。泄漏數(shù)組顯然會泄漏zvalzend_string,但是zvals沒有分配堆(我們在堆棧上分配),因此沒有泄漏報告。您應該習慣這樣一個事實,即忘記釋放/釋放諸如zend_array之類的復合結(jié)構(gòu)會導致大量泄漏,因為結(jié)構(gòu)經(jīng)常會嵌入結(jié)構(gòu),嵌入結(jié)構(gòu)等。

緩沖區(qū)上溢/下溢檢測

內(nèi)存泄漏很糟糕。這將導致您的程序一次或以后觸發(fā)OOM,并且將大大降低主機的速度,因為隨著時間的流逝,后者將獲得越來越少的可用內(nèi)存。這是內(nèi)存泄漏的征兆。

但是更糟的是:緩沖區(qū)越界訪問。訪問超出分配限制的指針是許多邪惡操作(例如在計算機上獲得root shell)的根源,因此您絕對應該防止它們。較輕的越界訪問也經(jīng)常會由于內(nèi)存損壞而導致程序崩潰。但是,這全部取決于硬件目標計算機,使用的編譯器和選項,操作系統(tǒng)內(nèi)存布局,使用的libc等……許多因素。

因此,越界訪問非常令人討厭,它們是炸彈,可能會爆炸,也可能不會爆炸,或者在一分鐘內(nèi),或者如果您非常幸運,它們將永遠不會爆炸。

  • Valgrind *是一個內(nèi)存調(diào)試器,因此能夠檢測到來自任何內(nèi)存區(qū)域(堆和堆棧)的任何越界訪問。這與查找泄漏使用的是相同的memcheck工具。

讓我們看一個簡單的例子:

PHP_MINIT_FUNCTION(pib)
{
    char *foo = malloc(16);
    foo[16] = 'a';
    foo[-1] = 'a';
}

這段代碼分配了一個緩沖區(qū),并故意在邊界后一個字節(jié)和邊界后一個字節(jié)寫入數(shù)據(jù)?,F(xiàn)在,如果您運行這樣的代碼,您就有大約兩次機會中有一次立即崩潰,然后隨機崩潰。您可能還已經(jīng)在PHP中創(chuàng)建了一個安全漏洞,但是它可能無法被遠程利用(這種行為很少見)。

Warning

越界訪問導致不確定的行為。無法預料會發(fā)生什么,但是請確保它不好(立即崩潰)或可怕(安全問題)。記得。

讓我們問一下valgrind,使用與之前完全相同的命令行來啟動它,除了輸出內(nèi)容外,其他都沒有改變:

==12802== Invalid write of size 1
==12802==    at 0xE896A98: zm_startup_pib (pib.c:1772)
==12802==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==12802==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==12802==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==12802==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)
==12802==    by 0x9D4541: php_module_startup (main.c:2260)
==12802==    by 0xB5802F: php_cli_startup (php_cli.c:427)
==12802==    by 0xB5A367: main (php_cli.c:1348)
==12802==  Address 0xeb488f0 is 0 bytes after a block of size 16 alloc'd
==12802==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12802==    by 0xE896A85: zm_startup_pib (pib.c:1771)
==12802==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==12802==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==12802==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==12802==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)
==12802==    by 0x9D4541: php_module_startup (main.c:2260)
==12802==    by 0xB5802F: php_cli_startup (php_cli.c:427)
==12802==    by 0xB5A367: main (php_cli.c:1348)
==12802==
==12802== Invalid write of size 1
==12802==    at 0xE896AA6: zm_startup_pib (pib.c:1773)
==12802==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==12802==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==12802==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==12802==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)
==12802==    by 0x9D4541: php_module_startup (main.c:2260)
==12802==    by 0xB5802F: php_cli_startup (php_cli.c:427)
==12802==    by 0xB5A367: main (php_cli.c:1348)
==12802==  Address 0xeb488df is 1 bytes before a block of size 16 alloc'd
==12802==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12802==    by 0xE896A85: zm_startup_pib (pib.c:1771)
==12802==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==12802==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==12802==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==12802==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)
==12802==    by 0x9D4541: php_module_startup (main.c:2260)
==12802==    by 0xB5802F: php_cli_startup (php_cli.c:427)
==12802==    by 0xB5A367: main (php_cli.c:1348)

這兩個無效的寫入都已被檢測到,現(xiàn)在您的目標是跟蹤并修復它們。

在這里,我們使用了一個示例,其中我們超出范圍地寫入內(nèi)存,這是最糟糕的情況,因為您的寫入操作成功后(可能會立即導致SIGSEGV)將覆蓋該指針旁邊的一些關鍵區(qū)域。當我們使用libc的malloc()進行分配時,我們將覆蓋libc用于管理和跟蹤其分配的關鍵頭尾塊。取決于許多因素(平臺,使用的libc,如何編譯等等),這將導致崩潰。

Valgrind也可能報告無效讀取。這意味著您將在分配的指針的范圍之外執(zhí)行內(nèi)存讀取操作。更好的情況是塊被覆蓋,但您仍然不應該訪問內(nèi)存區(qū)域,在這種情況下又可能會導致立即崩潰,或者稍后崩潰,或者永遠不會訪問?不要那樣做

Note

一旦您在valgrind的輸出中讀取“ Invalid”,那對您來說真的很不好。無論是無效的讀取還是寫入,您的代碼中都存在問題,因此您應該將這個問題視為高風險:現(xiàn)在就真正修復它。

這是有關字符串連接的第二個示例:

char *foo = strdup("foo");
char *bar = strdup("bar");

char *foobar = malloc(strlen("foo") + strlen("bar"));

memcpy(foobar, foo, strlen(foo));
memcpy(foobar + strlen("foo"), bar, strlen(bar));

fprintf(stderr, "%s", foobar);

free(foo);
free(bar);
free(foobar);

你能發(fā)現(xiàn)問題嗎?

讓我們問一下valgrind:

==13935== Invalid read of size 1
==13935==    at 0x4C30F74: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13935==    by 0x768203E: fputs (iofputs.c:33)
==13935==    by 0xE896B91: zm_startup_pib (pib.c:1779)
==13935==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==13935==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==13935==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==13935==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)
==13935==    by 0x9D4541: php_module_startup (main.c:2260)
==13935==    by 0xB5802F: php_cli_startup (php_cli.c:427)
==13935==    by 0xB5A367: main (php_cli.c:1348)
==13935==  Address 0xeb48986 is 0 bytes after a block of size 6 alloc'd
==13935==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13935==    by 0xE896B14: zm_startup_pib (pib.c:1774)
==13935==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==13935==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==13935==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==13935==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)
==13935==    by 0x9D4541: php_module_startup (main.c:2260)
==13935==    by 0xB5802F: php_cli_startup (php_cli.c:427)
==13935==    by 0xB5A367: main (php_cli.c:1348)

第1779行指向fprintf()調(diào)用。該調(diào)用確實要求fputs(),其本身稱為strlen()(均來自libc),在這里strlen()讀取1個字節(jié)無效。

我們只是忘記了\ 0來終止我們的字符串。我們傳遞fprintf()無效的字符串。它首先嘗試計算調(diào)用strlen()的字符串的長度。然后strlen()將掃描緩沖區(qū),直到找到\ 0,并且它將掃描緩沖區(qū)的邊界,因為我們忘記了對其進行零終止。我們在這里很幸運,strlen()僅從末尾傳遞一個字節(jié)。那可能更多,并且可能崩潰了,因為我們真的不知道下一個\ 0在內(nèi)存中的位置,這是隨機的。

解:

size_t len   = strlen("foo") + strlen("bar") + 1;   /* note the +1 for \0 */
char *foobar = malloc(len);

/* ... ... same code ... ... */

foobar[len - 1] = '\0'; /* terminate the string properly */

Note

上述錯誤是C語言中最常見的錯誤之一。它們被稱為一次性錯誤:您忘記僅分配一個字節(jié),但是由于以下原因,您將在代碼中產(chǎn)生大量問題那。

最后,這里是最后一個示例,展示了一個有余使用的場景。這也是C編程中的一個非常常見的錯誤,與錯誤的內(nèi)存訪問一樣嚴重:它創(chuàng)建了安全缺陷,可能導致非常討厭的行為。顯然,valgrind可以檢測到無用后使用。這是一個:

char *foo = strdup("foo");
free(foo);

memcpy(foo, "foo", sizeof("foo"));

同樣,這里是一個與PHP無關的PHP場景。我們釋放一個指針,然后再使用它。這是一個大錯誤。讓我們問一下valgrind:

==14594== Invalid write of size 1
==14594==    at 0x4C3245C: memcpy@GLIBC_2.2.5 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14594==    by 0xE896AA1: zm_startup_pib (pib.c:1774)
==14594==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==14594==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==14594==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==14594==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)
==14594==    by 0x9D4541: php_module_startup (main.c:2260)
==14594==    by 0xB5802F: php_cli_startup (php_cli.c:427)
==14594==    by 0xB5A367: main (php_cli.c:1348)
==14594==  Address 0xeb488e0 is 0 bytes inside a block of size 4 free'd
==14594==    at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14594==    by 0xE896A86: zm_startup_pib (pib.c:1772)
==14594==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==14594==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==14594==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==14594==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)
==14594==    by 0x9D4541: php_module_startup (main.c:2260)
==14594==    by 0xB5802F: php_cli_startup (php_cli.c:427)
==14594==    by 0xB5A367: main (php_cli.c:1348)
==14594==  Block was alloc'd at
==14594==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14594==    by 0x769E8D9: strdup (strdup.c:42)
==14594==    by 0xE896A70: zm_startup_pib (pib.c:1771)
==14594==    by 0xA774F7: zend_startup_module_ex (zend_API.c:1843)
==14594==    by 0xA77559: zend_startup_module_zval (zend_API.c:1858)
==14594==    by 0xA85AF5: zend_hash_apply (zend_hash.c:1508)
==14594==    by 0xA77B25: zend_startup_modules (zend_API.c:1969)
==14594==    by 0x9D4541: php_module_startup (main.c:2260)
==14594==    by 0xB5802F: php_cli_startup (php_cli.c:427)
==14594==    by 0xB5A367: main (php_cli.c:1348)

這里的一切再次變得清晰。

結(jié)論

在投入生產(chǎn)之前,請使用內(nèi)存調(diào)試器。正如您在本章中學到的那樣,您在計算中忘記的小字節(jié)可能導致可利用的安全漏洞。它還經(jīng)常(非常頻繁地)導致簡單的崩潰。這意味著您的擴展很酷,可以減少整個服務器(服務器)及其每個客戶端的數(shù)量。

C是一種非常嚴格的編程語言。您將獲得數(shù)十億字節(jié)的內(nèi)存來進行編程,并且必須安排這些內(nèi)存來執(zhí)行一些計算。但是請不要搞砸這種強大的功能:在最好的情況下(罕見),什么都不會發(fā)生,在更壞的情況下(非常常見),您會在這里和那里隨機崩潰,在最壞的情況下,您會創(chuàng)建一個漏洞在恰好可以被遠程利用的程序中...

您的工具嫻熟,聰明,請確實照顧機器內(nèi)存。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。

當前名稱:如何進行php內(nèi)存調(diào)試
本文地址:http://muchs.cn/article20/pdgdco.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供用戶體驗網(wǎng)站改版、手機網(wǎng)站建設小程序開發(fā)、網(wǎng)站策劃企業(yè)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設