众所周知,php 里面 header之前有输出的话,会报错,例如下面这样

 

就这个错误,我们开始查阅php源代码,到底是怎样做的,至于php源代码分析,安装,和调试时怎样配置的,我会专门写一篇文章去记录的,这里我是使用php-cli命令行的sapi,方便啊,首先我们先看看var_dump的实现啦

1.var_dump

我们知道,var_dump是php的标准函数啦,不是扩展里面的东西,所以会容易比较好找

我们可以见到啦,var_dump调用了php_var_dump函数啦

之后又调用了php_printf,我猜这个应该都是php内核用到的输出函数吧,我们再去php_printf看看吧

可见,php_printf模仿了c的printf,又是一个不定参数的函数,上面可以看到,又调用了PHPWRITE这个宏

实际是php_output_write函数啦

 

我们看看这个函数的逻辑吧

1,输出层是否激活,如果激活就调用php_output_op函数

2,如果不激活,那么直接输出到stderr去

2。 PHP_OUT_ACTIVATED由来

我们是用php-cli这个sapi的,跟踪了php启动过程,发觉,每个sapi都会调用一个函数,那就是

这个文件时在php-cli.c里面,有兴趣的读者可以看看这个,php在开始接受请求之前都会调用它的,截取一部分函数吧

我看看见了一个函数,php_out_activate函数啦

激活了输出层啦,证明可以输出啦

3 回到php_output_op函数

流程

   1 如果开启了缓冲区的话(obstart这种函数啦),就进入php_output_handler_op函数

   2,如果没有开启的话,就直接赋值给临时通道(context)

   3,如果真的有内容输出的话,就执行php_output_header函数

我们重点看php_output_header函数

4 php_output_header

 

这个函数很简单啦,就是设置当前输出行和该页面的名称,也就是我们调用var_dump的位置啦

具体有什么用,下面就知道啦

5,header函数实现

 

跟到sapi_header_op函数

在这里我们终于可以看到报错的哪行信息啦

header_sent什么时候开始设置呢

答案就是在在上面的 php_output_header函数里面调用的php_header里面啦

6 php_header

该函数的作用就是发送一个header(content-type:text/html);的东西,然后设置 SG(headers_sent) = 1

7 下面来分析为什么开启ob_start不会报错

  答案是开启了 因为开启了缓冲区,还记得上面php_output_op函数里面的一句代码吗

/*
* broken up for better performance:
*  - apply op to the one active handler; note that OG(active) might be popped off the stack on a flush
*  - or apply op to the handler stack
*/
if (OG(active) && (obh_cnt = zend_stack_count(&OG(handlers)))) {

 

上面的注释大家应该应该很清楚吗,如果我们调用了一个ob_start函数,php内核会申请一个handler结构同时为这个结构申请一个缓冲区 php_output_buffer

typedef struct _php_output_handler {
    char *name;
    size_t name_len;
    int flags;
    int level;
    size_t size;
    php_output_buffer buffer;
    void *opaq;
    void (*dtor)(void *opaq TSRMLS_DC);
    union {
        php_output_handler_user_func_t *user;
        php_output_handler_context_func_t internal;
    } func;
} php_output_handler;

当然,申请完缓冲区,就会初始化它然后把它压入栈啦,然后把handler赋给 OG(handlers)

 

下一篇说下,为什么header之前不能有输出,来更加深入httpd协议

php里面为什么header之前有输出报错 源码分析的更多相关文章

  1. SAP MM 公司间STO发货单输出报错 - 合并工厂AUC1和存储位置6002没有货物收货地点 - 之对策

    SAP MM 公司间STO发货单输出报错 - 合并工厂AUC1和存储位置6002没有货物收货地点 - 之对策 昨天收到客户业务部门报错,说是业务对交货单0080022298做POD失败.相关交货单的输 ...

  2. Mysql报错注入原理分析(count()、rand()、group by)

    Mysql报错注入原理分析(count().rand().group by) 0x00 疑问 一直在用mysql数据库报错注入方法,但为何会报错? 百度谷歌知乎了一番,发现大家都是把官网的结论发一下截 ...

  3. EasyPlayerPro(Windows)流媒体播放器开发之ffmpeg log输出报错

    EasyPlayerPro主要基于ffmpeg进行开发,在EasyPlayerPro开发过程中,曾遇到一个相对比较棘手的问题,该问题一般在播放不是很标准的流或者网络情况较差,容易出现丢帧的情况特别容易 ...

  4. scrapy shell 中文网站输出报错.记录.

    UnicodeDecodeError: 'gbk' codec can't decode bytes in position 381-382: illegal multibyte sequence 上 ...

  5. 【MySQL】MySQL同步报错-> received end packet from server, apparent master shutdown: Slave I/O thread: Failed reading log event, reconnecting to retry报错解决和分析

    [root@db-ft-db-48 ~]# tail -f /mysqlLog/beside_index_err.log 140102 20:42:26 [Note] Slave: received ...

  6. cocos2d-x在android中响应返回键编译报错的bug分析

    先看一段代码如何在Android中加入返回按键的响应 <span style="font-size:18px;">自己派生CCKeypadDelegate的子类,然后注 ...

  7. php源码分析之php_info输出中css样式是怎么来的

    我们经常使用echo phpinfo();查看php的配置信息,但是大家知道里面的css样式是怎么来的吗? 我们查看源码(php源码/ext/standard/css.c) PHPAPI void p ...

  8. MySQL主从检验一致性工具pt-table-checksum报错的案例分析

    [问题] 有同事反馈我们改造过的MySQL5.7.23版本,使用pt-table-checksum工具比较主从数据库的一致性时报错 Unsafe statement written to the bi ...

  9. MySQL Server has gone away报错原因汇总分析(转自:http://cenalulu.github.io/mysql/mysql-has-gone-away/)

    原因1. MySQL 服务宕了 判断是否属于这个原因的方法很简单,执行以下命令,查看mysql的运行时长 $ mysql -uroot -p -e "show global status l ...

随机推荐

  1. Linux卸载系统自带的httpd的方法

    卸载linux自带的httpd服务: 方法一: #rpm -e httpd 结果,出现以下错误 httpd-mmn = 20020628 is needed by (installed) mod_pe ...

  2. player/stage 学习---安装

    环境 ubuntu 14.04 一,工具安装 sudo apt-get install git cmake g++ fltk1.1-dev libjpeg8-dev libpng12-dev libg ...

  3. HTML CSS3 手风琴菜单

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel= ...

  4. HBase学习笔记

    关键类: HBaseAdmin 管理Hbase的,主要负责DDL操作 HTable 管理表中数据,主要负责DML操作 1.为了避免热点,更多的建表方法 在Shell中: },{SPLITS=>[ ...

  5. C# Index 定义索---引具体使用2

    窗体代码 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;usi ...

  6. Asp.net 后台添加Meta标签方法

    Asp.net 后台添加Meta标签方法包括keywords,CSS.JS 下面是从Asp.net 后台添加CSS.JS.Meta标签的写法,我们这里写成函数方便以后使用.如果函数放在页面类中, Pa ...

  7. 前端SPA框架一些看法

    说起前端框架,我个人主张有框架不如无框架,这个观点要先从框架和库的区别说起. 我所理解的库,解决的是代码或是模块级别的复用或者对复杂度的封装问题;而框架,更多的是对模式级别的复用和对程序组织的规范,这 ...

  8. js array 数组删除元素

    /* * 方法:Array.remove(dx) * 功能:根据元素位置值删除数组元素. * 参数:元素值 * 返回:在原数组上修改数组 */ Array.prototype.baoremove = ...

  9. c & c++中static的总结

    static 修饰的三种作用 (1) 静态局部变量 (2) 模块内的全局变量.函数,不可以被其他模块访问 (3) 类的静态成员 其中(3)只在c++中有. (1) 静态局部变量.局部变量一般在函数体内 ...

  10. Oracle中job的使用详解

    我们在项目开发中,常常会有一些复杂的业务逻辑.使用oracle的存储过程,可以大大减少java程序代码的编写工作量,而且存储过程执行在数据库上,这样可以利用oracle的良好性能支持,极大地提高程序执 ...