PHP用のZendメモリマネージャー
Zend Memory Manager
Zend Memory Manager は、ZendMM または ZMM と略されることが多く、C レイヤーです。動的 リクエスト バインド メモリを割り当ておよび解放する機能を提供するように設計されています。
上記の文の「リクエスト バインディング」に注目してください。
ZendMM は、主に 2 つの API 呼び出し malloc()/free()
で表される、libc の動的メモリ アロケーター上の単なる従来の層ではありません。 ZendMM は、リクエストの処理時に PHP が割り当てる必要があるリクエスト バインド メモリに関するものです。
関連する学習の推奨事項: PHP プログラミングの入門から熟練度まで
PHP の 2 つの主要な動的メモリ プール
PHP何も共有しないアーキテクチャ。そうですね、100% ではありません。ステップとサイクルについて詳しく説明します。
ZendMM には、libc の API をコピーすることで libc の動的アロケーターを置き換える API が付属しています。プログラマはリクエストを処理するときに libc のアロケータの代わりにこの API を使用する必要があります。 たとえば、PHP はリクエストを処理するときに、PHP ファイルを解析します。たとえば、これらは関数やクラスの宣言になります。コンパイラは、PHP ファイルのコンパイルを開始すると、検出したクラスと関数を保存するために動的メモリを割り当てます。ただし、PHP はリクエストの最後にこれらを解放します。デフォルトでは、PHP はリクエスト間でPHP は、同じプロセスで数百または数千のリクエストを処理できます。デフォルトでは、PHP は現在のリクエストが完了すると、そのリクエストに関する情報をすべて忘れます。
「忘れた」メッセージは、リクエストの処理中に割り当てられた動的バッファを解放すると解釈されます。これは、リクエストの処理中に、従来の libc 呼び出しを使用して動的メモリを割り当てることができないことを意味します。これは完全に有効ですが、バッファを解放するのを忘れる可能性があります。
多くの
情報を忘れます。 ただし、非常にまれな情報の中には、複数のリクエストにわたって保持する必要があるものもあります。しかし、これは一般的ではありません。リクエストによって変更されないものは何ですか? 永続
オブジェクトと呼ばれるもの。繰り返しますが、これは一般的な状況ではありません。たとえば、現在の PHP 実行可能パスはリクエスト間で変更されません。その情報は永続的に割り当てられます。つまり、従来の libc のmalloc ()
を呼び出して情報を割り当てます。 ######ほかに何か?何かの文字列。たとえば、$_SERVER PHP 配列がリクエストごとに作成されるため、"_SERVER" 文字列はリクエスト間で再利用されます。したがって、
"_SERVER"
覚えておく必要があります:PHP コアまたは拡張機能を作成する場合、動的メモリ割り当てには 2 つの方法があります:
リクエスト バインディングの決定動的割り当て。
- 永続的な動的割り当て。
-
- リクエスト バインディングの動的メモリ割り当て
- は、PHP がリクエストを処理するときにのみ実行されます (前後ではありません)。
ZendMM 動的メモリ割り当て API を使用してのみ実行する必要があります。 -
は拡張機能の設計では非常に一般的で、基本的に動的割り当ての 95% はリクエスト バインディングです。
- は ZendMM によって追跡されており、リークについて通知されます。
- 永続的な動的メモリ割り当て
- は、PHP がリクエストを処理している間は実行しないでください (禁止されているわけではありませんが、悪い考えです)。
は ZendMM によって追跡されず、リークについては通知されません。 -
は拡張機能ではまれです。
- また、すべての PHP ソース コードはこのメモリ レベルに基づいていることに注意してください。したがって、多くの内部構造は Zend メモリ マネージャーを使用して割り当てられます。ほとんどの場合、「永続的な」API を呼び出します。呼び出されると、従来の libc 割り当てが行われます。
- これはリクエストバインドされた割り当てです zend_string:
zend_string *foo = zend_string_init("foo", strlen("foo"), 0);
ログイン後にコピー
zend_string *foo = zend_string_init("foo", strlen("foo"), 1);
リクエスト限定割り当て:
zend_array ar; zend_hash_init(&ar, 8, NULL, NULL, 0);
永続的割り当て:
zend_array ar; zend_hash_init(&ar, 8, NULL, NULL, 1);
これは、すべての異なる Zend API で常に同じです。通常は最後のパラメータとして渡されます。
"0" は「ZendMM を使用してこの構造体を割り当てたいので、バインディングを要求する」を意味し、
"1"
"1"
は「ZendMM を使用してこの構造体を割り当てるため、バインディングが要求される」ことを意味します 従来の libc のmalloc() を呼び出します この構造を割り当てます。」 どうやら、これらの構造体は、構造体がどのように割り当てられたかを記憶する API を提供しており、破棄されたときに正しい解放関数が使用されるようです。したがって、次のようなコードになります:
zend_string_release(foo); zend_hash_destroy(&ar);
API は、これらの構造がリクエスト バインディングを使用して割り当てられているか、永続的に割り当てられているかを認識します。前者の場合は
efree() を使用して解放され、2 番目の場合は解放されます。最初の状況は libc の free()
です。Zend Memory Manager API
API は Zend/zend_alloc.h にあります
API は主に C マクロであり、関数ではないため、デバッグしてその動作を理解したい場合は、原則として、ご準備ください。これらの API は libc の関数をコピーしており、多くの場合関数名に「e」が追加されています。したがって、API についての詳細はあまり多くないので、間違えないように注意してください。
基本的に、最も頻繁に使用するのは emalloc(size_t)
と efree(void *)
です。
サイズ size
の単一の nmemb
を割り当て、領域をゼロに設定する ecalloc(size_t nmemb, size_t size)
も提供されます。経験豊富な C プログラマであれば、可能な限り、ecalloc()
ではなく ecalloc()
を使用するのが最善であることを知っているはずです。メモリ領域をゼロに設定します。これは、ポインタ エラーの検出に非常に役立ちます。 emalloc()
は基本的に libc malloc()
と同じように機能することに注意してください。さまざまなプールで十分な大きさの領域を検索し、最適なスペースを提供します。したがって、ガベージ コレクションされたポインターが生成される可能性があります。 次に、
、つまり emalloc(size * nmemb offset)
ですが、オーバーフローがチェックされます。この API 呼び出しは、提供する必要がある番号が信頼できないソース (ユーザーランドなど) からのものである場合に使用する必要があります。 文字列に関しては、
および estrndup(char *, size_t len)
を使用して、文字列またはバイナリ文字列をコピーできます。 何が起こっても、ZendMM から返されたポインタは、
ではなく、ZendMM の efree()
を呼び出して解放する必要があります。
ZendMM は次の機能を提供します:永続的な割り当てに関する説明。永続的な割り当ては、リクエスト間で有効なままです。通常、これを行うには通常の libc
malloc/freeを使用しますが、ZendMM には libc アロケーターのショートカット、つまり「永続的」API がいくつかあります。 API は
"p"
という文字で始まり、ZendMM 割り当てまたは永続的割り当てのいずれかを選択できます。したがって、pemalloc(size_t, 1) は単にmalloc()
であり、pefree(void *, 1)
はfree()
,# です。 ##pestrdup(void *, 1)は
strdup()です。ただ言って。
Zend Memory Manager Debug Shield
メモリ消費管理。
- メモリ リークの追跡と自動解放。 既知のサイズのバッファを事前に割り当て、ホット キャッシュをアイドル状態に保つことで、割り当てを高速化します。
- メモリ消費管理
memory_limit
に達すると何が起こるかはご存知でしょう。これは、ZendMM 経由で実行された割り当てが PHP ユーザーランドのmemory_get_usage() に反映されることも意味します。 これは、PHP プロセスのヒープ サイズを追跡するのに役立つため、拡張機能の開発者としては良いことです。
malloc()
などの従来の libc 呼び出しを使用する必要があります。いずれにせよ、注意して自分が何をしているのかを知ってください。 ZendMM を使用する場合は、大量のメモリを割り当てる必要があり、PHP のmemory_limit を超える可能性があります。したがって、別のアロケータ (libc など) を使用しますが、拡張機能によって現在のプロセス ヒープ サイズが増加することに注意してください。
memory_get_usage() は PHP では見ることができませんが、OS の機能 (/proc/{pid}/maps など) を使用して現在のヒープを分析できます。
Note ZendMM を完全に無効にする必要がある場合は、
環境変数を使用して PHP を起動できます。こうすることで、ZendMM API (emalloc() など) へのすべての呼び出しが libc 呼び出しに誘導され、ZendMM が無効になります。これは、メモリをデバッグする場合に特に便利です。閉じると、すべてのライブ ポインターが参照され、PHP のデバッグ ビルドを使用している場合は、メモリ リークについて警告が表示されます。 もう少しわかりやすく説明しましょう。現在のリクエストの最後に ZendMM がアクティブなメモリ ブロックを見つけた場合、それはこれらのメモリ ブロックがリークしていることを意味します。メモリを割り当てた人はメモリを解放しているはずなので、リクエストの終了時点で ZendMM ヒープ上にアクティブなメモリ ブロックが存在してはなりません。メモリ リーク トレース
ZendMM の主なルールを思い出してください。ZendMM はリクエストの開始時に開始され、リクエストを処理するために動的メモリが必要になったときに API を呼び出すことを期待します。現在のリクエストが終了すると、ZendMM はシャットダウンします。
如果您忘记释放块,它们将全部显示在 stderr上。此内存泄漏报告进程仅在以下情况下有效:
- 你正在使用 PHP 的调试构建
- 在 php.ini 中具有 report_memleaks = On(默认)
这是一个简单泄漏到扩展中的示例:
PHP_RINIT_FUNCTION(example) { void *foo = emalloc(128); }
在启动该扩展的情况下启动 PHP,在调试版本上会在 stderr 上生成:
[Fri Jun 9 16:04:59 2017] Script: '/tmp/foobar.php' /path/to/extension/file.c(123) : Freeing 0x00007fffeee65000 (128 bytes), script=/tmp/foobar.php === Total 1 memory leaks detected ===
当 Zend 内存管理器关闭时,在每个已处理请求的末尾,将生成这些行。
但是要当心:
- 显然,ZendMM 对持久分配或以不同于使用持久分配的方式执行的分配一无所知。因此,ZendMM 只能警告你有关它知道的分配信息,在这里不会报告每个传统的 libc 分配信息。
- 如果 PHP 以错误的方式关闭(我们称之为不正常关闭),ZendMM 将报告大量泄漏。这是因为引擎在错误关闭时会使用longjmp()调用 catch 块,防止清理所有内存的代码运行。因此,许多泄漏得到报告。尤其是在调用 PHP 的 exit()/ die()之后,或者在 PHP 的某些关键部分触发了致命错误时,就会发生这种情况。
- 如果你使用非调试版本的 PHP,则 stderr 上不会显示任何内容,ZendMM 是愚蠢的,但仍会清除程序员尚未明确释放的所有分配的请求绑定缓冲区
你必须记住的是 ZendMM 泄漏跟踪是一个不错的奖励工具,但它不能代替真正的 C 内存调试器。
ZendMM 内部设计
常见错误和错误
这是使用 ZendMM 时最常见的错误,以及你应该怎么做。
- 不处理请求时使用 ZendMM。
获取有关 PHP 生命周期的信息,以了解在扩展中何时处理请求,何时不处理。如果在请求范围之外使用 ZendMM(例如在MINIT()中),在处理第一个请求之前,ZendMM 会静默清除分配,并且可能会使用after-after-free:根本没有。
- 缓冲区上溢和下溢。
使用内存调试器。如果你在 ZendMM 返回的内存区域以下或过去写入内容,则将覆盖关键的 ZendMM 结构并触发崩溃。如果 ZendMM 能够为你检测到混乱,则可能会显示“zend_mm_heap损坏”的消息。堆栈追踪将显示从某些代码到某些 ZendMM 代码的崩溃。ZendMM 代码不会自行崩溃。如果你在 ZendMM 代码中间崩溃,那很可能意味着你在某个地方弄乱了指针。插入你喜欢的内存调试器,查找有罪的部分并进行修复。
- 混合 API 调用
如果分配一个 ZendMM 指针(即emalloc()
)并使用 libc 释放它(free()
),或相反的情况:你将崩溃。要严谨对待。另外,如果你将其不知道的任何指针传递给 ZendMM 的efree()
:将会崩溃。
以上がPHP用のZendメモリマネージャーの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。
