《UNIX Web服务器手册》
第十一章 先进的编程表格
11.1 用CGI编程
11.2 标记
11.3 管理HTML表格
11.3.1 表格结构和CGI
11.3.2 URL译码
11.3.3 POST方式
11.3.4 GET方式
11.4 动态生成页面
11.4.1 CGI.pm,使之更容易
11.4.2 FasCGI:网关的另一种实现方法
11.5 CGI参考
11.5.1 CGI环境变量
11.5.2 CGI标题
11.6 继续
test.c(test.cgi)
#include "stdio.h"
#include "stdlib.h"
void main()
{
int i = 0, n = 0;
#if 0/* for debug */
{
int v=0, *p1=&v, *p2=NULL;
*p2 = 0;
}
#endif
printf("Content type: text/plain\n\n");
if (getenv("CONTENT-LENGTH"))
n = atoi(getenv("CONTENT-LENGTH"));
for (i=0; i < n; putchar(getchar()))
{
i++;
}
putchar('\n');
putchar('a');
printf("test\n\n");
fflush(stdout);
}
6.2 异常中断调试
异常中断调试法是运行时调试CGI程序的最有效的方法(如调试文件上传,不以通过预置环境来调试)。原理是,故意构造异常(如让指针引用0地址中的变量),然后让操作系统和调试环境(如VC++)捕捉该异常并暂停(如同设置了一个断点)。通过将修改寄存器的值,使程序能够进一步运行后,再单步跟踪程序进行调试。
下面给出在Windows + VC++的环境下通过“异常中断”来调试CGI程序的示例,源程序可参考 $(EYBUILD_BASE)/project/demo/cgimain.c:
1. 在希望设置断点处手工添加能够导致程序异常的代码片断,类似如下程序:
#if 1/* for debug */
{int v=0, *p1=&v, *p2=NULL;
*p2 = 0;}
#endif
2. 编译并将CGI文件直接生成cgi-bin 目录。注意,不是“拷贝到”,否则将无法关联到源程序。不要运行该CGI程序,因为程序执行会异常。
3. 从浏览器上打开该 CGI 程序, 如 。这时Windows会弹出异常报告窗口了,如果你安装了 VC++, 那么在异常报告的窗口左下角就会有个“调试”按钮。
4. 点击“调试”按钮用VC++调试它,用 VC++打开后,断点就会停在“*p2 = 0;”所在行。
5. 从 View ->Debug Windows ->Registers 菜单打开寄存器窗口,这时你会发现其中的值, 类似如下:
EAX
|
=
|
0012FD1C
|
EBX
|
=
|
7FFD9000
|
ECX
|
=
|
00000000
|
EDX
|
=
|
00000001
|
ESI
|
=
|
00000000
|
EDI
|
=
|
0012FD20
|
EIP
|
=
|
0040130F
|
ESP
|
=
|
0012FCC8 |
6. 容易发现第二行 ECX = 00000000 ,它就是指针 p2 的值(因为被我们初始化它为 NULL )。而EAX寄存器中的值就是变量 v 的地址,这一点可以通查看指针变量 p1 的值证实。
7. 为了让程序能正常运行,可以通过让指针 p2也指向变量 v,方法是将ECX中的值修改成EAX中的值(即,先将光标定位到 ECX 的值处, 再将值改为 EAX 寄存器中的值)。
8. 从调试工具栏中选择下一步。OK! 程序可以单步向下执行了。