Configuring PHP for Development
As covered in Chapter 1, there are two special ./configure switches you'll want to use when building a development-friendly PHP whether you plan to write an extension to PHP or embed PHP in another application. These two switches should be used in addition to the other switches you'd normally use while building PHP.
enable-debug
The enable debug switch turns on a few critical functions within the PHP and Zend source trees. First, it enables reporting of leaked memory at the end of every request.
Recall from Chapter 3, "Memory Management," that the Zend Memory Manager will implicitly free per-request memory that was allocated but not explicitly freed prior to script end. By running a series of aggressive regression tests against newly developed code, leak points can be easily spotted and plugged prior to any public release. Take a look at the following code snippet:
void show_value(int n) { char *message = emalloc(1024); sprintf(message, "The value of n is %d ", n); php_printf("%s", message); }
If thisadmittedly sillyblock of code were executed during the course of a PHP request, it would leak 1,024 bytes of memory. Under ordinary circumstances ZendMM would quietly free that block at the end of script execution and not complain.
With enable-debug turned on, however, developers are treated to an error message giving them a clue about what needs to be addressed.
/cvs/php5/ext/sample/sample.c(33) : Freeing 0x084504B8 (1024 bytes), script=- === Total 1 memory leaks detected ===
This short but informative message tells you that ZendMM had to clean up after your mess and identifies exactly from where the lost memory block was allocated. Using this information, it's a simple matter to open the file, scroll down to the line in question, and add an appropriate call to efree(message) at the end of the function.
Memory leaks aren't the only problems you'll run into that are hard to track down, of course. Sometimes the problems are much more insidious, and far less telling. Let's say you've been working all night on a big patch that requires hitting a dozen files and changing a ton of code. When everything is in place, you confidently issue make, try out a sample script, and are treated to the following output:
$ sapi/cli/php -r 'myext_samplefunc();' Segmentation Fault
Well...that's just swell, but where could the problem be? Looking at your implementation of myext_samplefunc() doesn't reveal any obvious clues, and running it through gdb only shows a bunch of unknown symbols.
Once again, enable-debug lends a hand. By adding this switch to ./configure, the resulting PHP binary will contain all the debugging symbols needed by gdb or another core file examination program to show you where the problem occurred.
Rebuilding with this option, and triggering the crash through gdb, you're now treated to something like the following:
#0 0x1234567 php_myext_find_delimiter(str=0x1234567 "foo@#(FHVN)@x98xE0...", strlen=3, tsrm_ls=0x1234567) p = strchr(str, ',');
Suddenly the cause is clear. The str string is not a NULL terminated string, as evidenced by the garbage at the end, but a nonbinary-safe function was used on it. The underlying strchr() implementation tried scanning past the end of str's allocated memory and got into regions it didn't own, causing a segfault. A quick replacement using memchr() and the strlen parameter will prevent the crash.
enable-maintainer-zts
This second ./configure option forces PHP to be built with the Thread Safe Resource Manager(TSRM)/Zend Thread Safety(ZTS) layer enabled. This switch will add complexity and processing time when it's not otherwise needed, but for the purposes of development, you'll find that's a good thing. For a detailed description of what ZTS is and why you want to develop with it turned on, refer to Chapter 1.
enable-embed
One last ./configure switch of importance is only necessary if you'll be embedding PHP into another application. This option identifies that libphp5.so should be built as the selected SAPI in the same way that with-apxs will build mod_php5.so for embedding PHP specifically into Apache.