> The reason is that httpd memory usage patterns significantly differ from
> your simple example. E.g., there might be some memory block allocated at
> the end of the heap, which is not freed at the end of the request - and it
> will prevent all the rest of memory from being returned to the system.

Don't blame "httpd memory usage patterns" ! Of course they differ from
my simple example, but...

I've changed "a bit" files Zend/zend_alloc.c and ...h files.
I've just replaced the definitions of _emalloc, _efree... functions
with simple #defines, linking them back to standard malloc, free... and
so on functions.
The compilation - went OK (I suppose, debug can not be set).
The apache restart - OK.
Testing php - .... -  OK !

And the memory holding problem disapeared ! Memory is beeing returned
to system as the script finishes.

So...

It is not a good solution, of course, because Zend memory optimaliser is
turned off. But now we know, where should be put some afford to fix
the problem. The optimaliser propably leaves only some memory blocks
unfreed, but they make it unposible to return rest of memory back to
system. 

Am I not right ? May be not...

I send the changed files, but I suggest not to use them...
For example replacement of function _persist_alloc with value 1
is very ... hmm... controversial ? It should return the size of
block (as I suppose), but it was difficult to do that by simple means.

/*
   +----------------------------------------------------------------------+
   | Zend Engine                                                          |
   +----------------------------------------------------------------------+
   | Copyright (c) 1998-2000 Zend Technologies Ltd. (http://www.zend.com) |
   +----------------------------------------------------------------------+
   | This source file is subject to version 0.92 of the Zend license,     |
   | that is bundled with this package in the file LICENSE, and is        | 
   | available at through the world-wide-web at                           |
   | http://www.zend.com/license/0_92.txt.                                |
   | If you did not receive a copy of the Zend license and are unable to  |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.              |
   +----------------------------------------------------------------------+
   | Authors: Andi Gutmans <[EMAIL PROTECTED]>                                |
   |          Zeev Suraski <[EMAIL PROTECTED]>                                |
   +----------------------------------------------------------------------+
*/


#include <stdlib.h>

#include "zend.h"
#include "zend_alloc.h"
#include "zend_globals.h"
#include "zend_fast_cache.h"
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#ifndef ZTS
ZEND_API zend_alloc_globals alloc_globals;
#endif


#define ZEND_DISABLE_MEMORY_CACHE 0

#if ZEND_DEBUG
# define END_MAGIC_SIZE sizeof(long)
# define END_ALIGNMENT(size) 
(((size)%PLATFORM_ALIGNMENT)?(PLATFORM_ALIGNMENT-((size)%PLATFORM_ALIGNMENT)):0)
#else
# define END_MAGIC_SIZE 0
# define END_ALIGNMENT(size) 0
#endif


# if MEMORY_LIMIT
#  if ZEND_DEBUG
#define CHECK_MEMORY_LIMIT(s, rs) _CHECK_MEMORY_LIMIT(s, rs, __zend_filename, 
__zend_lineno)
#  else
#define CHECK_MEMORY_LIMIT(s, rs)       _CHECK_MEMORY_LIMIT(s, rs, NULL,0)
#  endif

#define _CHECK_MEMORY_LIMIT(s, rs, file, lineno) { AG(allocated_memory) += rs;\
                                                                if 
(AG(memory_limit)<AG(allocated_memory)) {\
                                                                        if 
((AG(memory_limit)+1048576)<AG(allocated_memory)) { \
                                                                                /* 
failed to handle this gracefully, exit() */ \
                                                                                
exit(1);        \
                                                                        }       \
                                                                        if 
(!AG(memory_exhausted)) {    \
                                                                                if 
(!file) { \
                                                                                       
 zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted (tried to allocate %d 
bytes)", AG(memory_limit),s); \
                                                                                } else 
{ \
                                                                                       
 zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted at %s:%d (tried to 
allocate %d bytes)", AG(memory_limit), file, lineno, s); \
                                                                                } \
                                                                                
AG(memory_exhausted)=1; \
                                                                        }       \
                                                                } \
                                                        }
# endif

#ifndef CHECK_MEMORY_LIMIT
#define CHECK_MEMORY_LIMIT(s, rs)
#endif


#define REMOVE_POINTER_FROM_LIST(p)                             \
        if (!p->persistent && p==AG(head)) {            \
                AG(head) = p->pNext;                                    \
        } else if (p->persistent && p==AG(phead)) {     \
                AG(phead) = p->pNext;                                   \
        } else {                                                                       
 \
                p->pLast->pNext = p->pNext;                             \
        }                                                                              
         \
        if (p->pNext) {                                                         \
                p->pNext->pLast = p->pLast;                             \
        }

#define ADD_POINTER_TO_LIST(p)          \
        if (p->persistent) {                    \
                p->pNext = AG(phead);           \
                if (AG(phead)) {                        \
                        AG(phead)->pLast = p;   \
                }                                                       \
                AG(phead) = p;                          \
        } else {                                                \
                p->pNext = AG(head);            \
                if (AG(head)) {                         \
                        AG(head)->pLast = p;    \
                }                                                       \
                AG(head) = p;                           \
        }                                                               \
        p->pLast = (zend_mem_header *) NULL;

#define DECLARE_CACHE_VARS              \
        unsigned int real_size;         \
        unsigned int cache_index;

#define REAL_SIZE(size) ((size+7) & ~0x7)

#define CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size)       \
        real_size = REAL_SIZE(size);                            \
        cache_index = real_size >> 3;

#define SIZE real_size

#define CACHE_INDEX cache_index

#if !NO_ZEND_ALLOC      //sielim!!!!!!!

ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
        zend_mem_header *p;
        DECLARE_CACHE_VARS
        ALS_FETCH();

        CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);

        if (!ZEND_DISABLE_MEMORY_CACHE && (CACHE_INDEX < MAX_CACHED_MEMORY) && 
(AG(cache_count)[CACHE_INDEX] > 0)) {
                p = AG(cache)[CACHE_INDEX][--AG(cache_count)[CACHE_INDEX]];
#if ZEND_DEBUG
                p->filename = __zend_filename;
                p->lineno = __zend_lineno;
                p->orig_filename = __zend_orig_filename;
                p->orig_lineno = __zend_orig_lineno;
                p->magic = MEM_BLOCK_START_MAGIC;
                p->reported = 0;
                /* Setting the thread id should not be necessary, because we fetched 
this block
                 * from this thread's cache
                 */
                AG(cache_stats)[CACHE_INDEX][1]++;
#endif
                p->persistent = 0;
                p->cached = 0;
                p->size = size;
                HANDLE_BLOCK_INTERRUPTIONS();
                ADD_POINTER_TO_LIST(p);
                HANDLE_UNBLOCK_INTERRUPTIONS();
                return (void *)((char *)p + sizeof(zend_mem_header) + 
PLATFORM_PADDING);
        } else {
#if ZEND_DEBUG
                if (CACHE_INDEX<MAX_CACHED_MEMORY) {
                        AG(cache_stats)[CACHE_INDEX][0]++;
                }
#endif
                p  = (zend_mem_header *) malloc(sizeof(zend_mem_header) + SIZE + 
PLATFORM_PADDING + END_ALIGNMENT(SIZE) + END_MAGIC_SIZE);
        }

        HANDLE_BLOCK_INTERRUPTIONS();

        if (!p) {
                fprintf(stderr,"FATAL:  emalloc():  Unable to allocate %ld bytes\n", 
(long) size);
#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
                kill(getpid(), SIGSEGV);
#else
                exit(1);
#endif
                HANDLE_UNBLOCK_INTERRUPTIONS();
                return (void *)p;
        }
        p->persistent = p->cached = 0;
        ADD_POINTER_TO_LIST(p);
        p->size = size; /* Save real size for correct cache output */
#if ZEND_DEBUG
        p->filename = __zend_filename;
        p->lineno = __zend_lineno;
        p->orig_filename = __zend_orig_filename;
        p->orig_lineno = __zend_orig_lineno;
        p->magic = MEM_BLOCK_START_MAGIC;
        p->reported = 0;
# ifdef ZTS
        p->thread_id = tsrm_thread_id();
# endif
        *((long *)(((char *) p) + 
sizeof(zend_mem_header)+SIZE+PLATFORM_PADDING+END_ALIGNMENT(SIZE))) = 
MEM_BLOCK_END_MAGIC;
#endif
#if MEMORY_LIMIT
        CHECK_MEMORY_LIMIT(size, SIZE);
#endif
        HANDLE_UNBLOCK_INTERRUPTIONS();
        return (void *)((char *)p + sizeof(zend_mem_header) + PLATFORM_PADDING);
}


ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
        zend_mem_header *p = (zend_mem_header *) ((char *)ptr - 
sizeof(zend_mem_header) - PLATFORM_PADDING);
        DECLARE_CACHE_VARS
        ALS_FETCH();

#if defined(ZTS) && ZEND_DEBUG
        if (p->thread_id != tsrm_thread_id()) {
                tsrm_error(TSRM_ERROR_LEVEL_ERROR, "Memory block allocated at %s:(%d) 
on thread %x freed at %s:(%d) on thread %x, ignoring",
                        p->filename, p->lineno, p->thread_id,
                        __zend_filename, __zend_lineno, tsrm_thread_id());
                return;
        }
#endif

        CALCULATE_REAL_SIZE_AND_CACHE_INDEX(p->size);
#if ZEND_DEBUG
        if (!_mem_block_check(ptr, 1 ZEND_FILE_LINE_RELAY_CC 
ZEND_FILE_LINE_ORIG_RELAY_CC)) {
                return;
        }
        memset(ptr, 0x5a, SIZE);
#endif

        if (!ZEND_DISABLE_MEMORY_CACHE 
                && !p->persistent && (CACHE_INDEX < MAX_CACHED_MEMORY) && 
(AG(cache_count)[CACHE_INDEX] < MAX_CACHED_ENTRIES)) {
                AG(cache)[CACHE_INDEX][AG(cache_count)[CACHE_INDEX]++] = p;
                p->cached = 1;
#if ZEND_DEBUG
                p->magic = MEM_BLOCK_CACHED_MAGIC;
#endif
                HANDLE_BLOCK_INTERRUPTIONS();
                REMOVE_POINTER_FROM_LIST(p);
                HANDLE_UNBLOCK_INTERRUPTIONS();
                return;
        }
        HANDLE_BLOCK_INTERRUPTIONS();
        REMOVE_POINTER_FROM_LIST(p);

#if MEMORY_LIMIT
        AG(allocated_memory) -= SIZE;
#endif
        
        free(p);
        HANDLE_UNBLOCK_INTERRUPTIONS();
}


ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC 
ZEND_FILE_LINE_ORIG_DC)
{
        void *p;
        int final_size=size*nmemb;
        
        HANDLE_BLOCK_INTERRUPTIONS();
        p = _emalloc(final_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
        if (!p) {
                HANDLE_UNBLOCK_INTERRUPTIONS();
                return (void *) p;
        }
        memset(p,(int)NULL, final_size);
        HANDLE_UNBLOCK_INTERRUPTIONS();
        return p;
}


ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC 
ZEND_FILE_LINE_ORIG_DC)
{
        zend_mem_header *p = (zend_mem_header *) ((char 
*)ptr-sizeof(zend_mem_header)-PLATFORM_PADDING);
        zend_mem_header *orig = p;
        DECLARE_CACHE_VARS
        ALS_FETCH();

        if (!ptr) {
                return _emalloc(size ZEND_FILE_LINE_RELAY_CC 
ZEND_FILE_LINE_ORIG_RELAY_CC);
        }

#if defined(ZTS) && ZEND_DEBUG
        if (p->thread_id != tsrm_thread_id()) {
                void *new_p;

                tsrm_error(TSRM_ERROR_LEVEL_ERROR, "Memory block allocated at %s:(%d) 
on thread %x reallocated at %s:(%d) on thread %x, duplicating",
                        p->filename, p->lineno, p->thread_id,
                        __zend_filename, __zend_lineno, tsrm_thread_id());
                new_p = _emalloc(size ZEND_FILE_LINE_RELAY_CC 
ZEND_FILE_LINE_ORIG_RELAY_CC);
                memcpy(new_p, ptr, p->size);
                return new_p;
        }
#endif

        CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);

        HANDLE_BLOCK_INTERRUPTIONS();
        REMOVE_POINTER_FROM_LIST(p);
        p = (zend_mem_header *) 
realloc(p,sizeof(zend_mem_header)+SIZE+PLATFORM_PADDING+END_ALIGNMENT(SIZE)+END_MAGIC_SIZE);

        if (!p) {
                if (!allow_failure) {
                        fprintf(stderr,"FATAL:  erealloc():  Unable to allocate %ld 
bytes\n", (long) size);
#if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID
                        kill(getpid(), SIGSEGV);
#else
                        exit(1);
#endif
                }
                ADD_POINTER_TO_LIST(orig);
                HANDLE_UNBLOCK_INTERRUPTIONS();
                return (void *)NULL;
        }
        ADD_POINTER_TO_LIST(p);
#if ZEND_DEBUG
        p->filename = __zend_filename;
        p->lineno = __zend_lineno;
        p->magic = MEM_BLOCK_START_MAGIC;
        *((long *)(((char *) p) + 
sizeof(zend_mem_header)+SIZE+PLATFORM_PADDING+END_ALIGNMENT(SIZE))) = 
MEM_BLOCK_END_MAGIC;
#endif  
#if MEMORY_LIMIT
        CHECK_MEMORY_LIMIT(size - p->size, SIZE - REAL_SIZE(p->size));
#endif
        p->size = size;

        HANDLE_UNBLOCK_INTERRUPTIONS();
        return (void *)((char *)p+sizeof(zend_mem_header)+PLATFORM_PADDING);
}


ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
        int length;
        char *p;

        length = strlen(s)+1;
        HANDLE_BLOCK_INTERRUPTIONS();
        p = (char *) _emalloc(length ZEND_FILE_LINE_RELAY_CC 
ZEND_FILE_LINE_ORIG_RELAY_CC);
        if (!p) {
                HANDLE_UNBLOCK_INTERRUPTIONS();
                return (char *)NULL;
        }
        HANDLE_UNBLOCK_INTERRUPTIONS();
        memcpy(p,s,length);
        return p;
}


ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC 
ZEND_FILE_LINE_ORIG_DC)
{
        char *p;

        HANDLE_BLOCK_INTERRUPTIONS();
        p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC 
ZEND_FILE_LINE_ORIG_RELAY_CC);
        if (!p) {
                HANDLE_UNBLOCK_INTERRUPTIONS();
                return (char *)NULL;
        }
        HANDLE_UNBLOCK_INTERRUPTIONS();
        memcpy(p,s,length);
        p[length]=0;
        return p;
}
#endif //sielim!!!!!! NO_ZEND_ALLOC

ZEND_API char *zend_strndup(const char *s, uint length)
{
        char *p;

        p = (char *) malloc(length+1);
        if (!p) {
                return (char *)NULL;
        }
        if (length) {
                memcpy(p,s,length);
        }
        p[length]=0;
        return p;
}


ZEND_API int zend_set_memory_limit(unsigned int memory_limit)
{
#if MEMORY_LIMIT
        ALS_FETCH();

        AG(memory_limit) = memory_limit;
        return SUCCESS;
#else
        return FAILURE;
#endif
}


ZEND_API void start_memory_manager(ALS_D)
{
#ifndef ZTS
        int i, j;
        void *cached_entries[MAX_CACHED_MEMORY][MAX_CACHED_ENTRIES];
#endif

        AG(phead) = AG(head) = NULL;
        
#if MEMORY_LIMIT
        AG(memory_limit)=1<<30;         /* rediculous limit, effectively no limit */
        AG(allocated_memory)=0;
        AG(memory_exhausted)=0;
#endif

        memset(AG(fast_cache_list_head), 0, sizeof(AG(fast_cache_list_head)));
        memset(AG(cache_count),0,sizeof(AG(cache_count)));

#ifndef ZTS
        /* Initialize cache, to prevent fragmentation */
        /* We can't do this in ZTS mode, because calling emalloc() from within 
start_memory_manager()
         * will yield an endless recursion calling to alloc_globals_ctor()
         */
        for (i=1; i<MAX_CACHED_MEMORY; i++) {
                for (j=0; j<PRE_INIT_CACHE_ENTRIES; j++) {
                        cached_entries[i][j] = emalloc(8*i);
                }
        }
        for (i=1; i<MAX_CACHED_MEMORY; i++) {
                for (j=0; j<PRE_INIT_CACHE_ENTRIES; j++) {
                        efree(cached_entries[i][j]);
                }
        }
#endif

#if ZEND_DEBUG
        memset(AG(cache_stats), 0, sizeof(AG(cache_stats)));
        memset(AG(fast_cache_stats), 0, sizeof(AG(fast_cache_stats)));
#endif
}


ZEND_API void shutdown_memory_manager(int silent, int clean_cache)
{
        zend_mem_header *p, *t;
        unsigned int fci, i, j;
#if ZEND_DEBUG
        int had_leaks=0;
#endif
        zend_fast_cache_list_entry *fast_cache_list_entry, 
*next_fast_cache_list_entry;
        ALS_FETCH();

        for (fci=0; fci<MAX_FAST_CACHE_TYPES; fci++) {
                fast_cache_list_entry = AG(fast_cache_list_head)[fci];
                while (fast_cache_list_entry) {
                        next_fast_cache_list_entry = fast_cache_list_entry->next;
                        efree(fast_cache_list_entry);
                        fast_cache_list_entry = next_fast_cache_list_entry;
                }
                AG(fast_cache_list_head)[fci] = NULL;
        }

        p=AG(head);
        t=AG(head);
        while (t) {
                if (!t->cached || clean_cache) {
#if ZEND_DEBUG
                        if (!t->cached && !t->reported) {
                                zend_mem_header *iterator;
                                int total_leak=0, total_leak_count=0;

                                had_leaks=1;
                                if (!silent) {
                                        
zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, t);
                                }
                                t->reported = 1;
                                for (iterator=t->pNext; iterator; 
iterator=iterator->pNext) {
                                        if (!iterator->cached
                                                && iterator->filename==t->filename
                                                && iterator->lineno==t->lineno) {
                                                total_leak += iterator->size;
                                                total_leak_count++;
                                                iterator->reported = 1;
                                        }
                                }
                                if (!silent && total_leak_count>0) {
                                        
zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *) (long) 
(total_leak_count));
                                }
                        }
#endif
#if MEMORY_LIMIT
                        AG(allocated_memory) -= t->size;
#endif
                        p = t->pNext;
                        REMOVE_POINTER_FROM_LIST(t);
                        free(t);
                        t = p;
                } else {
                        t = t->pNext;
                }
        }

        if(clean_cache) {
                for (i=1; i<MAX_CACHED_MEMORY; i++) {
                        for (j=0; j<AG(cache_count)[i]; j++) {
                                free(AG(cache)[i][j]);
                        }
                }
        }
#if MEMORY_LIMIT
        AG(memory_exhausted)=0;
#endif

#if (ZEND_DEBUG)
        do {
                zval display_memory_cache_stats;
                int i, j;

                if (clean_cache) {
                        /* we're shutting down completely, don't even touch the INI 
subsystem */
                        break;
                }
                if (zend_get_ini_entry("display_memory_cache_stats", 
sizeof("display_memory_cache_stats"), &display_memory_cache_stats)==FAILURE) {
                        break;
                }
                if (!atoi(display_memory_cache_stats.value.str.val)) {
                        break;
                }
                fprintf(stderr, "Memory cache statistics\n"
                                                "-----------------------\n\n"
                                                "[zval, %2ld]\t\t%d / %d (%.2f%%)\n"
                                                "[hash, %2ld]\t\t%d / %d (%.2f%%)\n",
                                                (long) sizeof(zval),
                                                
AG(fast_cache_stats)[ZVAL_CACHE_LIST][1], 
AG(fast_cache_stats)[ZVAL_CACHE_LIST][0]+AG(fast_cache_stats)[ZVAL_CACHE_LIST][1],
                                                ((double) 
AG(fast_cache_stats)[ZVAL_CACHE_LIST][1] / 
(AG(fast_cache_stats)[ZVAL_CACHE_LIST][0]+AG(fast_cache_stats)[ZVAL_CACHE_LIST][1]))*100,

                                                (long) sizeof(HashTable),
                                                
AG(fast_cache_stats)[HASHTABLE_CACHE_LIST][1], 
AG(fast_cache_stats)[HASHTABLE_CACHE_LIST][0]+AG(fast_cache_stats)[HASHTABLE_CACHE_LIST][1],

                                                ((double) 
AG(fast_cache_stats)[HASHTABLE_CACHE_LIST][1] / 
(AG(fast_cache_stats)[HASHTABLE_CACHE_LIST][0]+AG(fast_cache_stats)[HASHTABLE_CACHE_LIST][1]))*100);



                for (i=0; i<MAX_CACHED_MEMORY; i+=2) {
                        fprintf(stderr, "[%2d, %2d]\t\t", i, i+1);
                        for (j=0; j<2; j++) {
                                fprintf(stderr, "%d / %d (%.2f%%)\t\t",
                                                AG(cache_stats)[i+j][1], 
AG(cache_stats)[i+j][0]+AG(cache_stats)[i+j][1],
                                                ((double) AG(cache_stats)[i+j][1] / 
(AG(cache_stats)[i+j][0]+AG(cache_stats)[i+j][1]))*100);
                        }
                        fprintf(stderr, "\n");
                }
                                        
        } while (0);
#endif
}


#if ZEND_DEBUG
void zend_debug_alloc_output(char *format, ...)
{
        char output_buf[256];
        va_list args;

        va_start(args, format);
        vsprintf(output_buf, format, args);
        va_end(args);

#ifdef ZEND_WIN32
        OutputDebugString(output_buf);
#else
        fprintf(stderr, "%s", output_buf);
#endif
}


ZEND_API int _mem_block_check(void *ptr, int silent ZEND_FILE_LINE_DC 
ZEND_FILE_LINE_ORIG_DC)
{
        zend_mem_header *p = (zend_mem_header *) ((char *)ptr - 
sizeof(zend_mem_header) - PLATFORM_PADDING);
        int no_cache_notice=0;
        int valid_beginning=1;
        int had_problems=0;

        if (silent==2) {
                silent=1;
                no_cache_notice=1;
        }
        if (silent==3) {
                silent=0;
                no_cache_notice=1;
        }
        if (!silent) {
                zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL);
                zend_debug_alloc_output("---------------------------------------\n");
                zend_debug_alloc_output("%s(%d) : Block 0x%0.8lX status:\n" 
ZEND_FILE_LINE_RELAY_CC, (long) p);
                if (__zend_orig_filename) {
                        zend_debug_alloc_output("%s(%d) : Actual location (location 
was relayed)\n" ZEND_FILE_LINE_ORIG_RELAY_CC);
                }
                zend_debug_alloc_output("%10s\t","Beginning:  ");
        }

        switch (p->magic) {
                case MEM_BLOCK_START_MAGIC:
                        if (!silent) {
                                zend_debug_alloc_output("OK (allocated on %s:%d, %d 
bytes)\n", p->filename, p->lineno, p->size);
                        }
                        break; /* ok */
                case MEM_BLOCK_FREED_MAGIC:
                        if (!silent) {
                                zend_debug_alloc_output("Freed\n");
                                had_problems=1;
                        } else {
                                return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC 
ZEND_FILE_LINE_ORIG_RELAY_CC);
                        }
                        break;
                case MEM_BLOCK_CACHED_MAGIC:
                        if (!silent) {
                                if (!no_cache_notice) {
                                        zend_debug_alloc_output("Cached (allocated on 
%s:%d, %d bytes)\n", p->filename, p->lineno, p->size);
                                        had_problems=1;
                                }
                        } else {
                                if (!no_cache_notice) {
                                        return _mem_block_check(ptr, 0 
ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
                                }
                        }
                        break;
                default:
                        if (!silent) {
                                zend_debug_alloc_output("Overrun (magic=0x%0.8lX, 
expected=0x%0.8lX)\n", p->magic, MEM_BLOCK_START_MAGIC);
                        } else {
                                return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC 
ZEND_FILE_LINE_ORIG_RELAY_CC);
                        }
                        had_problems=1;
                        valid_beginning=0;
                        break;
        }


        if (valid_beginning
                && *((long *)(((char *) 
p)+sizeof(zend_mem_header)+REAL_SIZE(p->size)+PLATFORM_PADDING+END_ALIGNMENT(REAL_SIZE(p->size))))
 != MEM_BLOCK_END_MAGIC) {
                long magic_num = MEM_BLOCK_END_MAGIC;
                char *overflow_ptr, *magic_ptr=(char *) &magic_num;
                int overflows=0;
                int i;

                if (silent) {
                        return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC 
ZEND_FILE_LINE_ORIG_RELAY_CC);
                }
                had_problems=1;
                overflow_ptr = ((char *) 
p)+sizeof(zend_mem_header)+REAL_SIZE(p->size)+PLATFORM_PADDING;

                for (i=0; i<sizeof(long); i++) {
                        if (overflow_ptr[i]!=magic_ptr[i]) {
                                overflows++;
                        }
                }

                zend_debug_alloc_output("%10s\t", "End:");
                zend_debug_alloc_output("Overflown (magic=0x%0.8lX instead of 
0x%0.8lX)\n", 
                                *((long *)(((char *) p) + 
sizeof(zend_mem_header)+REAL_SIZE(p->size)+PLATFORM_PADDING+END_ALIGNMENT(REAL_SIZE(p->size)))),
 MEM_BLOCK_END_MAGIC);
                zend_debug_alloc_output("%10s\t","");
                if (overflows>=sizeof(long)) {
                        zend_debug_alloc_output("At least %d bytes overflown\n", 
sizeof(long));
                } else {
                        zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
                }
        } else if (!silent) {
                zend_debug_alloc_output("%10s\t", "End:");
                if (valid_beginning) {
                        zend_debug_alloc_output("OK\n");
                } else {
                        zend_debug_alloc_output("Unknown\n");
                }
        }

        if (had_problems) {
                int foo = 5;

                foo+=1;
        }
                
        if (!silent) {
                zend_debug_alloc_output("---------------------------------------\n");
        }
        return ((!had_problems) ? 1 : 0);
}


ZEND_API void _full_mem_check(int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
        zend_mem_header *p;
        int errors=0;
        ALS_FETCH();

        p = AG(head);
        

        zend_debug_alloc_output("------------------------------------------------\n");
        zend_debug_alloc_output("Full Memory Check at %s:%d\n" 
ZEND_FILE_LINE_RELAY_CC);

        while (p) {
                if (!_mem_block_check((void *)((char *)p + sizeof(zend_mem_header) + 
PLATFORM_PADDING), (silent?2:3) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)) 
{
                        errors++;
                }
                p = p->pNext;
        }
        zend_debug_alloc_output("End of full memory check %s:%d (%d errors)\n" 
ZEND_FILE_LINE_RELAY_CC, errors);
        zend_debug_alloc_output("------------------------------------------------\n");
}
#endif


#if !NO_ZEND_ALLOC  //sielim!!!!!!

ZEND_API int _persist_alloc(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
        zend_mem_header *p = (zend_mem_header *) ((char 
*)ptr-sizeof(zend_mem_header)-PLATFORM_PADDING);
        ALS_FETCH();

#if ZEND_DEBUG
        _mem_block_check(ptr, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
#endif

        HANDLE_BLOCK_INTERRUPTIONS();

        /* remove the block from the non persistent list */
        REMOVE_POINTER_FROM_LIST(p);

        p->persistent = 1;

        /* add the block to the persistent list */
        ADD_POINTER_TO_LIST(p);
        HANDLE_UNBLOCK_INTERRUPTIONS();
        return REAL_SIZE(p->size)+sizeof(zend_mem_header)+PLATFORM_PADDING;
}
#endif //sielim!!!!! NO_ZEND_ALLOC

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 */
/*
   +----------------------------------------------------------------------+
   | Zend Engine                                                          |
   +----------------------------------------------------------------------+
   | Copyright (c) 1998-2000 Zend Technologies Ltd. (http://www.zend.com) |
   +----------------------------------------------------------------------+
   | This source file is subject to version 0.92 of the Zend license,     |
   | that is bundled with this package in the file LICENSE, and is        | 
   | available at through the world-wide-web at                           |
   | http://www.zend.com/license/0_92.txt.                                |
   | If you did not receive a copy of the Zend license and are unable to  |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.              |
   +----------------------------------------------------------------------+
   | Authors: Andi Gutmans <[EMAIL PROTECTED]>                                |
   |          Zeev Suraski <[EMAIL PROTECTED]>                                |
   +----------------------------------------------------------------------+
*/


#ifndef ZEND_ALLOC_H
#define ZEND_ALLOC_H

#define NO_ZEND_ALLOC 1    //sielim !!!!!!

#include <stdio.h>

#ifdef ZTS
#include "../TSRM/TSRM.h"
#endif

#include "zend_globals_macros.h"

#define MEM_BLOCK_START_MAGIC   0x7312F8DCL
#define MEM_BLOCK_END_MAGIC     0x2A8FCC84L
#define MEM_BLOCK_FREED_MAGIC   0x99954317L
#define MEM_BLOCK_CACHED_MAGIC  0xFB8277DCL

typedef struct _zend_mem_header {
#if ZEND_DEBUG
        long magic;
        char *filename;
        uint lineno;
        int reported;
        char *orig_filename;
        uint orig_lineno;
# ifdef ZTS
        THREAD_T thread_id;
# endif
#endif
    struct _zend_mem_header *pNext;
    struct _zend_mem_header *pLast;
        unsigned int size:30;
        unsigned int persistent:1;
        unsigned int cached:1;
} zend_mem_header;

typedef union _align_test {
        void *ptr;
        double dbl;
        long lng;
} align_test;

#define MAX_CACHED_MEMORY       11  //11
#define MAX_CACHED_ENTRIES      256 //256
#define PRE_INIT_CACHE_ENTRIES  32  //32

#if (defined (__GNUC__) && __GNUC__ >= 2)
#define PLATFORM_ALIGNMENT (__alignof__ (align_test))
#else
#define PLATFORM_ALIGNMENT (sizeof(align_test))
#endif

#define PLATFORM_PADDING 
(((PLATFORM_ALIGNMENT-sizeof(zend_mem_header))%PLATFORM_ALIGNMENT+PLATFORM_ALIGNMENT)%PLATFORM_ALIGNMENT)



BEGIN_EXTERN_C()

ZEND_API char *zend_strndup(const char *s, unsigned int length);

/*by fs*/
#if NO_ZEND_ALLOC                                //sielim!!!!!!!
#define _emalloc(size)                          malloc((size) )                
//sielim!!!!!
#define _efree(ptr)                             free((ptr) )                   
//sielim!!!!!
#define _ecalloc(nmemb,size)                    calloc((nmemb), (size) )       
//sielim!!!!!
#define _erealloc(ptr,size,allow)               realloc((ptr), (size))         
//sielim!!!!!
#define _estrdup(s)                             strdup((s) )                   
//sielim!!!!!
#define _estrndup(s,length)                     zend_strndup((s), (length) )   
//sielim!!!!!
#define _persist_alloc(p)                       1  /*sielim Tutaj jest najbardziej 
sliska sprawa, bo funkcja powinna zwracac rozmiar bloku*/
#else                                            //sielim!!!!! NO_ZEND_ALLOC
ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC 
ZEND_FILE_LINE_ORIG_DC);
ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC 
ZEND_FILE_LINE_ORIG_DC);
ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC 
ZEND_FILE_LINE_ORIG_DC);
ZEND_API int _persist_alloc(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
#endif                                          //sielim!!!!! NO_ZEND_ALLOC

/* Standard wrapper macros */
#define emalloc(size)                                   _emalloc((size) 
ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define efree(ptr)                                              _efree((ptr) 
ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define ecalloc(nmemb,size)                             _ecalloc((nmemb), (size) 
ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define erealloc(ptr,size)                              _erealloc((ptr), (size),0 
ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define erealloc_recoverable(ptr,size)  _erealloc((ptr), (size),1 ZEND_FILE_LINE_CC 
ZEND_FILE_LINE_EMPTY_CC)
#define estrdup(s)                                              _estrdup((s) 
ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define estrndup(s,length)                              _estrndup((s), (length) 
ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define persist_alloc(p)                                _persist_alloc((p) 
ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)

/* Relay wrapper macros */
#define emalloc_rel(size)                                       _emalloc((size) 
ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define efree_rel(ptr)                                          _efree((ptr) 
ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define ecalloc_rel(nmemb, size)                        _ecalloc((nmemb), (size) 
ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define erealloc_rel(ptr, size)                         _erealloc((ptr), (size), 0 
ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define erealloc_recoverable_rel(ptr, size)     _erealloc((ptr), (size), 1 
ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define estrdup_rel(s)                                          _estrdup((s) 
ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define estrndup_rel(s, length)                         _estrndup((s), (length) 
ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define persist_alloc_rel(p)                            _persist_alloc((p) 
ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)

/* Selective persistent/non persistent allocation macros */
#define pemalloc(size,persistent) ((persistent)?malloc(size):emalloc(size))
#define pefree(ptr,persistent)  ((persistent)?free(ptr):efree(ptr))
#define pecalloc(nmemb,size,persistent) 
((persistent)?calloc((nmemb),(size)):ecalloc((nmemb),(size)))
#define perealloc(ptr,size,persistent) 
((persistent)?realloc((ptr),(size)):erealloc((ptr),(size)))
#define perealloc_recoverable(ptr,size,persistent) 
((persistent)?realloc((ptr),(size)):erealloc_recoverable((ptr),(size)))
#define pestrdup(s,persistent) ((persistent)?strdup(s):estrdup(s))

#define safe_estrdup(ptr)  ((ptr)?(estrdup(ptr)):(empty_string))
#define safe_estrndup(ptr,len) ((ptr)?(estrndup((ptr),(len))):(empty_string))

ZEND_API int zend_set_memory_limit(unsigned int memory_limit);

ZEND_API void start_memory_manager(ALS_D);
ZEND_API void shutdown_memory_manager(int silent, int clean_cache);

#if ZEND_DEBUG
ZEND_API int _mem_block_check(void *ptr, int silent ZEND_FILE_LINE_DC 
ZEND_FILE_LINE_ORIG_DC);
ZEND_API void _full_mem_check(int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
void zend_debug_alloc_output(char *format, ...);
#define mem_block_check(ptr, silent) _mem_block_check(ptr, silent ZEND_FILE_LINE_CC 
ZEND_FILE_LINE_EMPTY_CC)
#define full_mem_check(silent) _full_mem_check(silent ZEND_FILE_LINE_CC 
ZEND_FILE_LINE_EMPTY_CC)
#else
#define mem_block_check(type, ptr, silent)
#define full_mem_check(silent)
#endif


END_EXTERN_C()

#endif

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 */
-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to