php zend引擎解析原理,PHP内核分析-Zend引擎-栈结构及操作-程序员宅基地

技术标签: php zend引擎解析原理  

Zend引擎对栈常量的定义:

#define ZEND_STACK_APPLY_TOPDOWN 1//由顶部向底部对栈进行遍历操作

#define ZEND_STACK_APPLY_BOTTOMUP 2//由底部向顶部对栈进行遍历操作

#define STACK_BLOCK_SIZE 64 //每次扩容的元素个数

看一下Zend引擎栈的数据结构定义:

typedef struct _zend_stack {

int top;//栈顶,用数字表示(从底到顶分别为0,1,2...)

int max;//栈当前最大元素个数,当栈满后会将max+STACK_BLOCK_SZE来进行扩容

void **elements;//栈元素指针数组

} zend_stack;

栈的常用操作如下:

//初始化栈,不包含zend_stack结构的内存分配。仅初始化top, max的值和elements的值。

ZEND_API int zend_stack_init(zend_stack *stack)

{

stack->top = 0;

stack->max = 0;

stack->elements = NULL;

return SUCCESS;

}

//以memcpy的方式将element元素复制入栈。size表示元素的大小。

ZEND_API int zend_stack_push(zend_stack *stack, const void *element, int size)

{

if (stack->top >= stack->max) { /* we need to allocate more memory */

stack->elements = (void **) erealloc(stack->elements,

(sizeof(void **) * (stack->max += STACK_BLOCK_SIZE)));

//当栈满后会将max+STACK_BLOCK_SZE来进行扩容

if (!stack->elements) {

return FAILURE;

}

}

stack->elements[stack->top] = (void *) emalloc(size);

memcpy(stack->elements[stack->top], element, size);

return stack->top++;

}

//获取栈顶部元素的指针,并赋值给**element

ZEND_API int zend_stack_top(const zend_stack *stack, void **element)

{

if (stack->top > 0) {

*element = stack->elements[stack->top - 1];

return SUCCESS;

} else {

*element = NULL;

return FAILURE;

}

}

//删除栈顶。

ZEND_API int zend_stack_del_top(zend_stack *stack)

{

if (stack->top > 0) {

efree(stack->elements[--stack->top]);

}

return SUCCESS;

}

//返回栈顶元素的指针的值

ZEND_API int zend_stack_int_top(const zend_stack *stack)

{

int *e;

if (zend_stack_top(stack, (void **) &e) == FAILURE) {

return FAILURE; /* this must be a negative number, since negative numbers can't be address numbers */

} else {

return *e;

}

}

//根据stack->top的值来判断栈是否为空.stack->top用数字来表示的好处。

ZEND_API int zend_stack_is_empty(const zend_stack *stack)

{

if (stack->top == 0) {

return 1;

} else {

return 0;

}

}

//销毁栈。其实也可以while(stack->top--){zend_stack_del_top(stack)};stack->elements = NULL;

ZEND_API int zend_stack_destroy(zend_stack *stack)

{

int i;

if (stack->elements) {

for (i = 0; i < stack->top; i++) {

efree(stack->elements[i]);

}

efree(stack->elements);

stack->elements = NULL;

}

return SUCCESS;

}

//直接返回栈数据元素指针

ZEND_API void **zend_stack_base(const zend_stack *stack)

{

return stack->elements;

}

//返回栈元素个数。这就是用数字来表示栈顶而不直接用指针来表示的好处。

ZEND_API int zend_stack_count(const zend_stack *stack)

{

return stack->top;

}

//遍历栈并执行函数。注意,传入的函数返回值为int型。为0时表示函数执行成功,为1时表示函数执行失败。

ZEND_API void zend_stack_apply(zend_stack *stack, int type, int (*apply_function)(void *element))

{

int i;

switch (type) {

//自顶向下执行

case ZEND_STACK_APPLY_TOPDOWN:

for (i=stack->top-1; i>=0; i--) {

if (apply_function(stack->elements[i])) {

break;

}

}

break;

//自底向上执行

case ZEND_STACK_APPLY_BOTTOMUP:

for (i=0; itop; i++) {

if (apply_function(stack->elements[i])) {

break;

}

}

break;

}

}

//与zend_stack_apply函数一样,都是遍历栈并执行函数。但此函数支持调用函数传递参数。

ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg)

{

int i;

switch (type) {

case ZEND_STACK_APPLY_TOPDOWN:

for (i=stack->top-1; i>=0; i--) {

if (apply_function(stack->elements[i], arg)) {

break;

}

}

break;

case ZEND_STACK_APPLY_BOTTOMUP:

for (i=0; itop; i++) {

if (apply_function(stack->elements[i], arg)) {

break;

}

}

break;

}

}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_36440677/article/details/116248592

智能推荐

[Windows]_[初级]_[Release程序的崩溃报告minidump解决方案]_minidump 格式的崩溃报告-程序员宅基地

文章浏览阅读3.9k次。场景:1. Release的程序崩溃时,崩溃报告可以让开发人员查明代码哪里出了问题,用处大大的。2. 只有用VS的编译器才支持,所以MinGW就无缘了。3. 使用了未处理异常过滤处理函数._minidump 格式的崩溃报告

华为云服务之弹性云服务器ECS的深度使用和云端实践_华为云ecs虚拟化技术栈-程序员宅基地

文章浏览阅读1.7k次,点赞5次,收藏9次。什么是弹性云服务器ECS?ECS的产品架构是什么?它有哪些优势和有应用场景?弹性云服务器ECS的使用流程是怎样的?如何运用弹性云服务器ECS搭建微信公众号后台并收发文本消息?让我们带着这些疑问,去弹性云服务器ECS的世界里一探究竟,玩转ECS!!..._华为云ecs虚拟化技术栈

微信小程序蓝牙连接打印机_微信小程序蓝牙打印失败-程序员宅基地

文章浏览阅读6.8k次,点赞2次,收藏27次。微信小程序蓝牙连接打印机_微信小程序蓝牙打印失败

python安装opencv库、提示找不到pip_【Python】pip安装opencv-python包失败的一个处理方法...-程序员宅基地

文章浏览阅读687次。出现的问题在Windows10系统中,在cmd中(或者在pycharm的Terminal中)输入pip install opencv-python会出现如下报错ERROR: Exception:Traceback (most recent call last):File "C:\Users\bzm84\Anaconda3\lib\site-packages\pip\_vendor\urllib3\..._file "c:\users\lneovo\anaconda3\envs\tf2.1\lib\site-packages\pip\_vendor\url

举例说明使用MATLAB Coder从MATLAB生成C/C++代码步骤_matlab 生成c-程序员宅基地

文章浏览阅读1.1k次。MATLAB Coder可以从MATLAB代码生成独立的、可读性强、可移植的C/C++代码。使用MATLAB Coder产生代码的3个步骤:准备用于产生代码的MATLAB算法;检查MATLAB代码的兼容性(有些matlab代码语句并不能生成c/c++代码);产生最终使用的源代码或MEX。利用MATLAB Coder生成c++代码,并在vs2008中验证:一个简单的例子,两数相乘_matlab 生成c

如何下载、选择dbSNP数据库的变异位点vcf文件(hg19/hg38)_dbsnp信息下载-程序员宅基地

文章浏览阅读7.6k次,点赞4次,收藏7次。创作日志:下载的增强子数据文件里,没给增强子中包含的SNP信息,所以要自己写脚本补充。本来是想通过爬虫的方法在dbSNP的网站上边爬取边补充,但是谁知道dbSNP的搜索功能做得那么垃圾!于是就只能下载dbSNP的变异位点文件,然后再自己做处理。当我经历了九九八十一难终于下载并解压好了120+G的vcf文件后,打印信息的时候tmd发现自己下载错了版本,我要用的是hg19,却下载成了hg38,欲哭无泪… 文件名不标版本真的很气人。于是读了读README文档,谁让以前不读呢。具体步骤 注意:由于下载的v_dbsnp信息下载

随便推点

内存刷脏机制触发的系统故障案例一则-程序员宅基地

文章浏览阅读1.4k次,点赞50次,收藏22次。LINUX刷脏导致系统阻塞案例一则

Python程序员真的觉得写代码比女朋友重要吗?这个回答16,205 人赞同!!_python要写代码吗-程序员宅基地

文章浏览阅读296次。我的第一个女友95年的,她出身很好,很庄重。我的第二个女友94年的,她是个自由的女孩,敢爱敢恨,常带着一顶米色的草帽。我的第三个女友91年的,她是个简洁的女孩,身边常捏着一本你没听过名字的诗集。。。。尽管我内心认为爱情应该从一而终,找与自己年龄相仿的然后善始善终,但我却克制不住自己的,因为我并不太喜欢太小的女孩,我喜欢那种年龄相对我大一些的,所以我后来又交往了一个73年的,和一个82年的姑娘..._python要写代码吗

小米架构调整:拆分成立人工智能部,直接向CEO雷军汇报-程序员宅基地

文章浏览阅读2.7k次。允中 发自 凹非寺量子位 出品 | 公众号 QbitAI小米昨天宣布再次进行大规模组织架构调整。其中最为关键的举措,就是进一步加强对技术团队的重视。包括任命崔宝秋担任小米..._小米集团季旭简历

Clay Codes — 从生成矩阵的角度来看_clay codes: moulding mds codes to yield an msr cod-程序员宅基地

文章浏览阅读1.4k次,点赞2次,收藏9次。Clay Codes ( Clay Codes: Moulding MDS Codes to Yield an MSR Code ) 是FAST18 上提出的一种编码方法,文章地址,Clay 码能够将一般的MDS 码(最优容错)转化为具有最优修复的编码方法,具有以下性质:Minimum Storage (最小存储开销,同经典RS码和最小存储再生码,MSR) Maximum Failure Tolerance(最大容错,即 (n,k)-Clay 码可以容任意n-k 失效) Optimal Repair_clay codes: moulding mds codes to yield an msr code

HTML的弹性布局用法_html弹性布局怎么用-程序员宅基地

文章浏览阅读7.4k次,点赞13次,收藏55次。HTMl中的弹性布局的实际用法弹性布局是html中十分方便的一个布局,它可以让结构中的内容自适应不同的分辨率,简化了许多繁琐的代码,今天就简单来介绍一下弹性布局的用法。弹性布局:display:flex;顾名思义,就是让内容变得像弹簧一样具有弹性,在需要内容自适应的结构中,它是一个极其方便的工具,它分为主轴和侧轴两个轴,就像X轴跟Y轴一样。弹性布局的语法分为两块儿:一.加给父容器的语法。二..._html弹性布局怎么用

过滤器Filter_"@webfilter(filtername = \"encodingfilter\",urlpat-程序员宅基地

文章浏览阅读63次。29. 过滤器Filter:● 为什么要用过滤器?项目开发中,经常会用到重复代码的实现。1、请求每个servlet都要设置编码2、判断用户是否登录,只有登录了才有操作权限。●过滤器相关Api:interface Filter 过滤器核心接口1、init(FilterConfig filterConfig) 初始化方法,在服务器启动的时候就执行2、doFilter(ServletRequest request, ServletResponse response,.._"@webfilter(filtername = \"encodingfilter\",urlpatterns = \"/*\")"