When writing PHP extensions, it seems that parameters (i.e., variables passed to zend_parse_parameters) do not need to be free. Example:
operating normally: test("Hello World"); // Print Hello World There is no need to worry about memory leaks in the test function here. PHP will automatically help us recycle these variables used to save parameters. So how does php do it? To explain this problem, we still have to look at how PHP passes parameters. EG (argument_stack) introduction To put it simply, a stack specifically used to store parameters is saved in EG in PHP, named argument_stack. Whenever a function call occurs, php will push the incoming parameters into EG (argument_stack). Once the function call ends, the EG (argument_stack) is cleared and waits for the next function call. Regarding the struct structure and purpose of EG (argument_stack), there are some differences between the implementation of php5.2 and 5.3. This article mainly takes 5.2 as an example, and we will discuss the changes in 5.3+ later.
The above picture is a rough diagram of argument_stack in 5.2, which looks simple and clear. Among them, the top and bottom of the stack are fixed to NULL. The parameters received by the function are pushed onto the stack in order from left to right. Note that an additional long value will be pushed in at the end, indicating the number of parameters in the stack (10 in the picture above). What are the parameters that are pushed into argument_stack? In fact, they are pointers of zval type. The zva they point to may be a CV variable, a variable with is_ref=1, or a constant number or constant string. EG (argument_stack) is specifically implemented as zend_ptr_stack type in php5.2:
Initialize argument_stack The work of initializing argument_stack occurs before PHP processes a specific request. To be more precise, it is during the startup process of the PHP interpreter. In the init_executor function we found the following 2 lines:
These two lines represent, respectively, initialization EG(ar gument_stack), Then push a NULL. Since EG is a global variable, all data in EG (argument_stack) are all 0 before zend_ptr_stack_init is actually called. zend_ptr_stack_init implementation is very simple.
Once argument_stack is initialized, it will NULL is pushed. There is no need to go into detail here, this NULL actually has no meaning. After NULL is pushed into the stack, the actual memory distribution of the entire argument_stack is as follows:
Push parameters onto stack After pushing the first NULL, once another parameter is pushed onto the stack, the following actions will occur in argument_stack: stack->top++; *(stack->top_element++) = parameter; Use a simple php code to illustrate the problem:
The above code passes in a string constant when calling foo. Therefore, what is actually pushed onto the stack is a zval pointing to the storage "hello world". Use vld to view the compiled opcode:
SEND_VAL instruction actually does is push "hello world" into argument_stack.
The argument_stack after the push is completed is: Number of parameters As mentioned earlier, it is not actually just pushing all the parameters onto the stack. PHP will also push an additional number to represent the number of parameters. This work does not occur during the SEND_XXX command. In fact, before actually executing the function, PHP will push the number of parameters onto the stack. Continuing to use the above example, the DO_FCALL instruction is used to call the foo function. Before calling foo, php will automatically fill in the last block of argument_stack.
The first instruction is RECV, which is literally used to obtain the parameters in the stack. In fact, SEND_VAL and RECV have a somewhat corresponding feeling. SEND_VAL before each function call, RECV is performed inside the function. Why not say it is completely corresponding? In fact, the RECV instruction is not necessarily required. RECV is generated only when a user-defined function is called. The extension functions we write and the built-in functions that come with PHP will not have RECV. It should be pointed out that each SEND_VAL and RECV can only process one parameter. That is to say, if there are multiple parameters in the parameter passing process, several SEND_VAL and several RECV will be generated. This leads to a very interesting topic, what is the order of passing in parameters and getting parameters? The answer is that SEND_VAL will push the parameters onto the stack from left to right, while RECV will get the parameters from left to right.
zend_assign_to_variable_reference and zend_receive will complete "getting parameters". "Getting parameters" is not easy to understand. What does it actually do? In the final analysis, it is very simple. "Getting parameters" is to add this parameter to the "symbol table" during the execution of the current function, which specifically corresponds to EG (current_execute_data)->symbol_table. In this example, after RECV is completed, there is a symbol 'str' in the symbol_table in the function body, and its value is "hello world". But argument_stack has not changed at all, because RECV only reads parameters and does not perform a pop operation on the stack. Clean argument_stack
The print_r inside foo is also a function call, so the stack push-->stack clear operation will also occur. Therefore the argument_stack before print_r is executed is:
After print_r is executed, argument_stack returns to the state where foo just finished RECV. The specific process of calling print_r is not the focus of this article. What we care about is how PHP cleans up argument_stack after calling foo. As can be seen from the do_fcall code snippet shown above, the cleaning work is completed by zend_ptr_stack_clear_multiple.
Pay attention to clearing the zval pointer in the stack here, zval_ptr_dtor is used. zval_ptr_dtor will decrement the refcount by 1. Once the refcount is reduced to 0, the memory area storing the variable will be truly recycled. In the example of this article, after foo is called, the zval status of "hello world" is saved:
Since refcount is only 1, zval_ptr_dtor will actually destroy "hello world" from memory. The memory status of argument_stack after stack elimination is: It can be seen that the argument_stack in the above picture is the same as it was just initialized. At this point argument_stack is truly ready for the next function call. Back to the question at the beginning of the article... Why no need for free(str)? After understanding argument_stack, you can easily understand this problem. Because str points to the memory address where "hello world" is actually stored in zval. Assume that the extension function is as follows:
then call
will output "Hello world". Although when we call test, we do not pass the reference of $a, but the actual effect is equivalent to test(&$a). Simply put, there is only one copy of $a in memory, whether it is in the CV array or argument_stack. zend_parse_parameters does not copy a copy of the data for function execution, and in fact it cannot do so. Therefore, when the function is completed, if $a is not used elsewhere, PHP will help us free it when cleaning up argument_stack. If it is still used by other code, it cannot be freed manually, otherwise the memory area of $a will be destroyed. Note that not every variable used in writing extension functions will be automatically recycled by PHP. So when it’s time to be free, don’t be soft:) |

PHP is used to build dynamic websites, and its core functions include: 1. Generate dynamic content and generate web pages in real time by connecting with the database; 2. Process user interaction and form submissions, verify inputs and respond to operations; 3. Manage sessions and user authentication to provide a personalized experience; 4. Optimize performance and follow best practices to improve website efficiency and security.

PHP uses MySQLi and PDO extensions to interact in database operations and server-side logic processing, and processes server-side logic through functions such as session management. 1) Use MySQLi or PDO to connect to the database and execute SQL queries. 2) Handle HTTP requests and user status through session management and other functions. 3) Use transactions to ensure the atomicity of database operations. 4) Prevent SQL injection, use exception handling and closing connections for debugging. 5) Optimize performance through indexing and cache, write highly readable code and perform error handling.

Using preprocessing statements and PDO in PHP can effectively prevent SQL injection attacks. 1) Use PDO to connect to the database and set the error mode. 2) Create preprocessing statements through the prepare method and pass data using placeholders and execute methods. 3) Process query results and ensure the security and performance of the code.

PHP and Python have their own advantages and disadvantages, and the choice depends on project needs and personal preferences. 1.PHP is suitable for rapid development and maintenance of large-scale web applications. 2. Python dominates the field of data science and machine learning.

PHP is widely used in e-commerce, content management systems and API development. 1) E-commerce: used for shopping cart function and payment processing. 2) Content management system: used for dynamic content generation and user management. 3) API development: used for RESTful API development and API security. Through performance optimization and best practices, the efficiency and maintainability of PHP applications are improved.

PHP makes it easy to create interactive web content. 1) Dynamically generate content by embedding HTML and display it in real time based on user input or database data. 2) Process form submission and generate dynamic output to ensure that htmlspecialchars is used to prevent XSS. 3) Use MySQL to create a user registration system, and use password_hash and preprocessing statements to enhance security. Mastering these techniques will improve the efficiency of web development.

PHP and Python each have their own advantages, and choose according to project requirements. 1.PHP is suitable for web development, especially for rapid development and maintenance of websites. 2. Python is suitable for data science, machine learning and artificial intelligence, with concise syntax and suitable for beginners.

PHP is still dynamic and still occupies an important position in the field of modern programming. 1) PHP's simplicity and powerful community support make it widely used in web development; 2) Its flexibility and stability make it outstanding in handling web forms, database operations and file processing; 3) PHP is constantly evolving and optimizing, suitable for beginners and experienced developers.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

WebStorm Mac version
Useful JavaScript development tools

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment