亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

是什么導致我的測試 PHP 擴展出現這種奇怪的內存損壞?

是什么導致我的測試 PHP 擴展出現這種奇怪的內存損壞?

PHP
滄海一幻覺 2022-01-14 16:06:35
我最近需要一個已編譯信號名稱的列表,這樣我就可以打印出很好的消息,例如“被 SIGINT (2) 中斷”。get_defined_constants()對此無法使用,因為它在完全不相關的定義中(具有相同的整數值)混雜在一起SIGINT等SIGTRAP。信號名稱根據操作系統映射到不同的值,有時它們并沒有全部編譯到 PHP 中,所以最直接的干凈解決方案是一個新函數,它只返回一個已編譯的信號名稱數組。嗯……一個將靜態數組返回給 PHP 用戶空間的函數……這聽起來像是一個非常好的第一個源代碼黑客項目,對吧?不 :)下面的代碼(再往下一點)是一個超級最小化的測試用例,它說明了我撞到的非常奇怪的磚墻。我有一個GINIT函數將擴展全局初始化test_array為一個數組,然后我用一些條目(就像我的更改pcntl所做的那樣)填充它add_assoc_long()(在這種情況下sprintf(),用于為數組鍵生成虛擬字符串,如!!!, """,###等)。test_test1()然后,我有一個ZVAL_COPY預構建test_array的演示功能return_value。請打鼓;看看當我嘗試和print_r()結果時會發生什么:Array(    [PWD] => 0    [i336] => 1    [LOGNAME] => 2    [tty] => 3    [HOME] => 4    [LANG] => 5    [user] => 6    [xterm] => 7    [TERM] => 8    [i336] => 9    [USER] => 10    [:0] => 11    [DISPLAY] => 12    [SHLVL] => 13    [9:22836] => 14    [PATH] => 15    [111] => 16    [222] => 17    [333] => 18    [444] => 19    [555] => 20    [666] => 21    [777] => 22    [888] => 23    [999] => 24    [HG] => 25    [MAIL] => 26    [OLDPWD] => 27    [] => 28    [] => 29    [] => 30    [STDIN] => 31    [STDOUT] => 32    [STDERR] => 33    [print_r] => 34    [DDD] => 35    [EEE] => 36    [FFF] => 37    [GGG] => 38    [HHH] => 39    [III] => 40    [JJJ] => 41    [KKK] => 42    [LLL] => 43    [MMM] => 44    [NNN] => 45    [OOO] => 46    [PPP] => 47    [QQQ] => 48    [RRR] => 49<<snipped>>真正奇怪的是條目 0 到 15 已損壞。條目 16 到 24 可以;條目 25 到 34 已損壞;條目 35 上很好。0-15 / 16-24 有一種奇怪的感覺;25-34 / 35-∞沒有。除了一些關于我做錯了什么的提示(我知道我有一些倒退...... :) ),我非常想了解為什么PHP 將部分看似隨機的環境變量轉儲到我的數組中!我停止自己的探索/解決過程并發布此問題的主要原因是我意識到我不知道我不知道什么,再加上我不知道該去哪里嘗試解決這。提供 PHP 文檔的資源越來越多,但不幸的是,弄清楚如何完成簡單的任務似乎需要將來自不同來源的大量細節拼湊在一起(我被困在表面上看起來很簡單的東西上) .我也有關于我正在閱讀的內容的最新程度的問題。一個例子:ZEND_MODULE_GLOBALS_ACCESSOR()用于線程安全地訪問每個模塊的全局值的宏被使用了 37 次(看起來只有不到一半的內容ext/)。然而,我讀過的所有信息,包括在 phpinternals.net 和 phpinternalsbook.net 等網站上,都指定了包含特定 5 行 #define 的硬性要求,以便設置對模塊全局變量的訪問。我偶然發現了前面提到的宏,它在 PHP 本身中實現了#define,因此沒有人必須通過閱讀源代碼來自己做。我可以完全接受事情并不完全同步——也許那個宏是新的。但是,我在哪里可以找到最新的參考信息來回答我的問題?
查看完整描述

1 回答

?
慕少森

TA貢獻2019條經驗 獲得超9個贊

GINIT 在請求啟動之前被調用。array_init()并且add_assoc_long()(和大多數其他 API)使用按請求分配器。

您可以改用持久分配(通過使用較低級別的 zend_hash 和 zend_string API 并傳遞 persistent=1 標志),但仍然不允許您從 PHP 函數返回這樣的數組,因為這違反了 PHP 內存模型(不允許在請求期間更改持久值的引用計數)。

如果你想使用 per-request 分配器在全局中放置一個值,你需要在 RINIT 中這樣做(然后在 RSHUTDOWN 中銷毀)。這些處理程序作為每個請求的一部分被調用。

盡管對于您的特定用例,我建議根本不使用全局變量,而是在每次調用函數時重新構造數組。它不是性能關鍵的。


查看完整回答
反對 回復 2022-01-14
  • 1 回答
  • 0 關注
  • 146 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號