• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ******************************************************************************
3 *
4 *   Copyright (C) 1997-2015, International Business Machines
5 *   Corporation and others.  All Rights Reserved.
6 *
7 ******************************************************************************
8 *
9 * File CMEMORY.H
10 *
11 *  Contains stdlib.h/string.h memory functions
12 *
13 * @author       Bertrand A. Damiba
14 *
15 * Modification History:
16 *
17 *   Date        Name        Description
18 *   6/20/98     Bertrand    Created.
19 *  05/03/99     stephen     Changed from functions to macros.
20 *
21 ******************************************************************************
22 */
23 
24 #ifndef CMEMORY_H
25 #define CMEMORY_H
26 
27 #include "unicode/utypes.h"
28 
29 #include <stddef.h>
30 #include <string.h>
31 #include "unicode/localpointer.h"
32 
33 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
34 #include <stdio.h>
35 #endif
36 
37 #if U_DEBUG
38 
39 /*
40  * The C++ standard requires that the source pointer for memcpy() & memmove()
41  * is valid, not NULL, and not at the end of an allocated memory block.
42  * In debug mode, we read one byte from the source point to verify that it's
43  * a valid, readable pointer.
44  */
45 
46 U_CAPI void uprv_checkValidMemory(const void *p, size_t n);
47 
48 #define uprv_memcpy(dst, src, size) ( \
49     uprv_checkValidMemory(src, 1), \
50     U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size))
51 #define uprv_memmove(dst, src, size) ( \
52     uprv_checkValidMemory(src, 1), \
53     U_STANDARD_CPP_NAMESPACE memmove(dst, src, size))
54 
55 #else
56 
57 #define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)
58 #define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)
59 
60 #endif  /* U_DEBUG */
61 
62 /**
63  * \def UPRV_LENGTHOF
64  * Convenience macro to determine the length of a fixed array at compile-time.
65  * @param array A fixed length array
66  * @return The length of the array, in elements
67  * @internal
68  */
69 #define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
70 #define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
71 #define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
72 
73 U_CAPI void * U_EXPORT2
74 uprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1);
75 
76 U_CAPI void * U_EXPORT2
77 uprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2);
78 
79 U_CAPI void U_EXPORT2
80 uprv_free(void *mem);
81 
82 U_CAPI void * U_EXPORT2
83 uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2);
84 
85 /**
86  * This should align the memory properly on any machine.
87  * This is very useful for the safeClone functions.
88  */
89 typedef union {
90     long    t1;
91     double  t2;
92     void   *t3;
93 } UAlignedMemory;
94 
95 /**
96  * Get the least significant bits of a pointer (a memory address).
97  * For example, with a mask of 3, the macro gets the 2 least significant bits,
98  * which will be 0 if the pointer is 32-bit (4-byte) aligned.
99  *
100  * ptrdiff_t is the most appropriate integer type to cast to.
101  * size_t should work too, since on most (or all?) platforms it has the same
102  * width as ptrdiff_t.
103  */
104 #define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask))
105 
106 /**
107  * Get the amount of bytes that a pointer is off by from
108  * the previous UAlignedMemory-aligned pointer.
109  */
110 #define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1)
111 
112 /**
113  * Get the amount of bytes to add to a pointer
114  * in order to get the next UAlignedMemory-aligned address.
115  */
116 #define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
117 
118 /**
119   *  Heap clean up function, called from u_cleanup()
120   *    Clears any user heap functions from u_setMemoryFunctions()
121   *    Does NOT deallocate any remaining allocated memory.
122   */
123 U_CFUNC UBool
124 cmemory_cleanup(void);
125 
126 /**
127  * A function called by <TT>uhash_remove</TT>,
128  * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete
129  * an existing key or value.
130  * @param obj A key or value stored in a hashtable
131  * @see uprv_deleteUObject
132  */
133 typedef void U_CALLCONV UObjectDeleter(void* obj);
134 
135 /**
136  * Deleter for UObject instances.
137  * Works for all subclasses of UObject because it has a virtual destructor.
138  */
139 U_CAPI void U_EXPORT2
140 uprv_deleteUObject(void *obj);
141 
142 #ifdef __cplusplus
143 
144 U_NAMESPACE_BEGIN
145 
146 /**
147  * "Smart pointer" class, deletes memory via uprv_free().
148  * For most methods see the LocalPointerBase base class.
149  * Adds operator[] for array item access.
150  *
151  * @see LocalPointerBase
152  */
153 template<typename T>
154 class LocalMemory : public LocalPointerBase<T> {
155 public:
156     /**
157      * Constructor takes ownership.
158      * @param p simple pointer to an array of T items that is adopted
159      */
160     explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
161 #if U_HAVE_RVALUE_REFERENCES
162     /**
163      * Move constructor, leaves src with isNull().
164      * @param src source smart pointer
165      */
LocalMemory(LocalMemory<T> && src)166     LocalMemory(LocalMemory<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
167         src.ptr=NULL;
168     }
169 #endif
170     /**
171      * Destructor deletes the memory it owns.
172      */
~LocalMemory()173     ~LocalMemory() {
174         uprv_free(LocalPointerBase<T>::ptr);
175     }
176 #if U_HAVE_RVALUE_REFERENCES
177     /**
178      * Move assignment operator, leaves src with isNull().
179      * The behavior is undefined if *this and src are the same object.
180      * @param src source smart pointer
181      * @return *this
182      */
183     LocalMemory<T> &operator=(LocalMemory<T> &&src) U_NOEXCEPT {
184         return moveFrom(src);
185     }
186 #endif
187     /**
188      * Move assignment, leaves src with isNull().
189      * The behavior is undefined if *this and src are the same object.
190      *
191      * Can be called explicitly, does not need C++11 support.
192      * @param src source smart pointer
193      * @return *this
194      */
moveFrom(LocalMemory<T> & src)195     LocalMemory<T> &moveFrom(LocalMemory<T> &src) U_NOEXCEPT {
196         delete[] LocalPointerBase<T>::ptr;
197         LocalPointerBase<T>::ptr=src.ptr;
198         src.ptr=NULL;
199         return *this;
200     }
201     /**
202      * Swap pointers.
203      * @param other other smart pointer
204      */
swap(LocalMemory<T> & other)205     void swap(LocalMemory<T> &other) U_NOEXCEPT {
206         T *temp=LocalPointerBase<T>::ptr;
207         LocalPointerBase<T>::ptr=other.ptr;
208         other.ptr=temp;
209     }
210     /**
211      * Non-member LocalMemory swap function.
212      * @param p1 will get p2's pointer
213      * @param p2 will get p1's pointer
214      */
swap(LocalMemory<T> & p1,LocalMemory<T> & p2)215     friend inline void swap(LocalMemory<T> &p1, LocalMemory<T> &p2) U_NOEXCEPT {
216         p1.swap(p2);
217     }
218     /**
219      * Deletes the array it owns,
220      * and adopts (takes ownership of) the one passed in.
221      * @param p simple pointer to an array of T items that is adopted
222      */
adoptInstead(T * p)223     void adoptInstead(T *p) {
224         uprv_free(LocalPointerBase<T>::ptr);
225         LocalPointerBase<T>::ptr=p;
226     }
227     /**
228      * Deletes the array it owns, allocates a new one and reset its bytes to 0.
229      * Returns the new array pointer.
230      * If the allocation fails, then the current array is unchanged and
231      * this method returns NULL.
232      * @param newCapacity must be >0
233      * @return the allocated array pointer, or NULL if the allocation failed
234      */
235     inline T *allocateInsteadAndReset(int32_t newCapacity=1);
236     /**
237      * Deletes the array it owns and allocates a new one, copying length T items.
238      * Returns the new array pointer.
239      * If the allocation fails, then the current array is unchanged and
240      * this method returns NULL.
241      * @param newCapacity must be >0
242      * @param length number of T items to be copied from the old array to the new one;
243      *               must be no more than the capacity of the old array,
244      *               which the caller must track because the LocalMemory does not track it
245      * @return the allocated array pointer, or NULL if the allocation failed
246      */
247     inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
248     /**
249      * Array item access (writable).
250      * No index bounds check.
251      * @param i array index
252      * @return reference to the array item
253      */
254     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
255 };
256 
257 template<typename T>
allocateInsteadAndReset(int32_t newCapacity)258 inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
259     if(newCapacity>0) {
260         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
261         if(p!=NULL) {
262             uprv_memset(p, 0, newCapacity*sizeof(T));
263             uprv_free(LocalPointerBase<T>::ptr);
264             LocalPointerBase<T>::ptr=p;
265         }
266         return p;
267     } else {
268         return NULL;
269     }
270 }
271 
272 
273 template<typename T>
allocateInsteadAndCopy(int32_t newCapacity,int32_t length)274 inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
275     if(newCapacity>0) {
276         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
277         if(p!=NULL) {
278             if(length>0) {
279                 if(length>newCapacity) {
280                     length=newCapacity;
281                 }
282                 uprv_memcpy(p, LocalPointerBase<T>::ptr, length*sizeof(T));
283             }
284             uprv_free(LocalPointerBase<T>::ptr);
285             LocalPointerBase<T>::ptr=p;
286         }
287         return p;
288     } else {
289         return NULL;
290     }
291 }
292 
293 /**
294  * Simple array/buffer management class using uprv_malloc() and uprv_free().
295  * Provides an internal array with fixed capacity. Can alias another array
296  * or allocate one.
297  *
298  * The array address is properly aligned for type T. It might not be properly
299  * aligned for types larger than T (or larger than the largest subtype of T).
300  *
301  * Unlike LocalMemory and LocalArray, this class never adopts
302  * (takes ownership of) another array.
303  */
304 template<typename T, int32_t stackCapacity>
305 class MaybeStackArray {
306 public:
307     /**
308      * Default constructor initializes with internal T[stackCapacity] buffer.
309      */
MaybeStackArray()310     MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
311     /**
312      * Destructor deletes the array (if owned).
313      */
~MaybeStackArray()314     ~MaybeStackArray() { releaseArray(); }
315     /**
316      * Returns the array capacity (number of T items).
317      * @return array capacity
318      */
getCapacity()319     int32_t getCapacity() const { return capacity; }
320     /**
321      * Access without ownership change.
322      * @return the array pointer
323      */
getAlias()324     T *getAlias() const { return ptr; }
325     /**
326      * Returns the array limit. Simple convenience method.
327      * @return getAlias()+getCapacity()
328      */
getArrayLimit()329     T *getArrayLimit() const { return getAlias()+capacity; }
330     // No "operator T *() const" because that can make
331     // expressions like mbs[index] ambiguous for some compilers.
332     /**
333      * Array item access (const).
334      * No index bounds check.
335      * @param i array index
336      * @return reference to the array item
337      */
338     const T &operator[](ptrdiff_t i) const { return ptr[i]; }
339     /**
340      * Array item access (writable).
341      * No index bounds check.
342      * @param i array index
343      * @return reference to the array item
344      */
345     T &operator[](ptrdiff_t i) { return ptr[i]; }
346     /**
347      * Deletes the array (if owned) and aliases another one, no transfer of ownership.
348      * If the arguments are illegal, then the current array is unchanged.
349      * @param otherArray must not be NULL
350      * @param otherCapacity must be >0
351      */
aliasInstead(T * otherArray,int32_t otherCapacity)352     void aliasInstead(T *otherArray, int32_t otherCapacity) {
353         if(otherArray!=NULL && otherCapacity>0) {
354             releaseArray();
355             ptr=otherArray;
356             capacity=otherCapacity;
357             needToRelease=FALSE;
358         }
359     }
360     /**
361      * Deletes the array (if owned) and allocates a new one, copying length T items.
362      * Returns the new array pointer.
363      * If the allocation fails, then the current array is unchanged and
364      * this method returns NULL.
365      * @param newCapacity can be less than or greater than the current capacity;
366      *                    must be >0
367      * @param length number of T items to be copied from the old array to the new one
368      * @return the allocated array pointer, or NULL if the allocation failed
369      */
370     inline T *resize(int32_t newCapacity, int32_t length=0);
371     /**
372      * Gives up ownership of the array if owned, or else clones it,
373      * copying length T items; resets itself to the internal stack array.
374      * Returns NULL if the allocation failed.
375      * @param length number of T items to copy when cloning,
376      *        and capacity of the clone when cloning
377      * @param resultCapacity will be set to the returned array's capacity (output-only)
378      * @return the array pointer;
379      *         caller becomes responsible for deleting the array
380      */
381     inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
382 private:
383     T *ptr;
384     int32_t capacity;
385     UBool needToRelease;
386     T stackArray[stackCapacity];
releaseArray()387     void releaseArray() {
388         if(needToRelease) {
389             uprv_free(ptr);
390         }
391     }
392     /* No comparison operators with other MaybeStackArray's. */
393     bool operator==(const MaybeStackArray & /*other*/) {return FALSE;}
394     bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;}
395     /* No ownership transfer: No copy constructor, no assignment operator. */
MaybeStackArray(const MaybeStackArray &)396     MaybeStackArray(const MaybeStackArray & /*other*/) {}
397     void operator=(const MaybeStackArray & /*other*/) {}
398 
399     // No heap allocation. Use only on the stack.
400     //   (Declaring these functions private triggers a cascade of problems:
401     //      MSVC insists on exporting an instantiation of MaybeStackArray, which
402     //      requires that all functions be defined.
403     //      An empty implementation of new() is rejected, it must return a value.
404     //      Returning NULL is rejected by gcc for operator new.
405     //      The expedient thing is just not to override operator new.
406     //      While relatively pointless, heap allocated instances will function.
407     // static void * U_EXPORT2 operator new(size_t size);
408     // static void * U_EXPORT2 operator new[](size_t size);
409 #if U_HAVE_PLACEMENT_NEW
410     // static void * U_EXPORT2 operator new(size_t, void *ptr);
411 #endif
412 };
413 
414 template<typename T, int32_t stackCapacity>
resize(int32_t newCapacity,int32_t length)415 inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
416     if(newCapacity>0) {
417 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
418       ::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T));
419 #endif
420         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
421         if(p!=NULL) {
422             if(length>0) {
423                 if(length>capacity) {
424                     length=capacity;
425                 }
426                 if(length>newCapacity) {
427                     length=newCapacity;
428                 }
429                 uprv_memcpy(p, ptr, length*sizeof(T));
430             }
431             releaseArray();
432             ptr=p;
433             capacity=newCapacity;
434             needToRelease=TRUE;
435         }
436         return p;
437     } else {
438         return NULL;
439     }
440 }
441 
442 template<typename T, int32_t stackCapacity>
orphanOrClone(int32_t length,int32_t & resultCapacity)443 inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
444     T *p;
445     if(needToRelease) {
446         p=ptr;
447     } else if(length<=0) {
448         return NULL;
449     } else {
450         if(length>capacity) {
451             length=capacity;
452         }
453         p=(T *)uprv_malloc(length*sizeof(T));
454 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
455       ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
456 #endif
457         if(p==NULL) {
458             return NULL;
459         }
460         uprv_memcpy(p, ptr, length*sizeof(T));
461     }
462     resultCapacity=length;
463     ptr=stackArray;
464     capacity=stackCapacity;
465     needToRelease=FALSE;
466     return p;
467 }
468 
469 /**
470  * Variant of MaybeStackArray that allocates a header struct and an array
471  * in one contiguous memory block, using uprv_malloc() and uprv_free().
472  * Provides internal memory with fixed array capacity. Can alias another memory
473  * block or allocate one.
474  * The stackCapacity is the number of T items in the internal memory,
475  * not counting the H header.
476  * Unlike LocalMemory and LocalArray, this class never adopts
477  * (takes ownership of) another memory block.
478  */
479 template<typename H, typename T, int32_t stackCapacity>
480 class MaybeStackHeaderAndArray {
481 public:
482     /**
483      * Default constructor initializes with internal H+T[stackCapacity] buffer.
484      */
MaybeStackHeaderAndArray()485     MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {}
486     /**
487      * Destructor deletes the memory (if owned).
488      */
~MaybeStackHeaderAndArray()489     ~MaybeStackHeaderAndArray() { releaseMemory(); }
490     /**
491      * Returns the array capacity (number of T items).
492      * @return array capacity
493      */
getCapacity()494     int32_t getCapacity() const { return capacity; }
495     /**
496      * Access without ownership change.
497      * @return the header pointer
498      */
getAlias()499     H *getAlias() const { return ptr; }
500     /**
501      * Returns the array start.
502      * @return array start, same address as getAlias()+1
503      */
getArrayStart()504     T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
505     /**
506      * Returns the array limit.
507      * @return array limit
508      */
getArrayLimit()509     T *getArrayLimit() const { return getArrayStart()+capacity; }
510     /**
511      * Access without ownership change. Same as getAlias().
512      * A class instance can be used directly in expressions that take a T *.
513      * @return the header pointer
514      */
515     operator H *() const { return ptr; }
516     /**
517      * Array item access (writable).
518      * No index bounds check.
519      * @param i array index
520      * @return reference to the array item
521      */
522     T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
523     /**
524      * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
525      * If the arguments are illegal, then the current memory is unchanged.
526      * @param otherArray must not be NULL
527      * @param otherCapacity must be >0
528      */
aliasInstead(H * otherMemory,int32_t otherCapacity)529     void aliasInstead(H *otherMemory, int32_t otherCapacity) {
530         if(otherMemory!=NULL && otherCapacity>0) {
531             releaseMemory();
532             ptr=otherMemory;
533             capacity=otherCapacity;
534             needToRelease=FALSE;
535         }
536     }
537     /**
538      * Deletes the memory block (if owned) and allocates a new one,
539      * copying the header and length T array items.
540      * Returns the new header pointer.
541      * If the allocation fails, then the current memory is unchanged and
542      * this method returns NULL.
543      * @param newCapacity can be less than or greater than the current capacity;
544      *                    must be >0
545      * @param length number of T items to be copied from the old array to the new one
546      * @return the allocated pointer, or NULL if the allocation failed
547      */
548     inline H *resize(int32_t newCapacity, int32_t length=0);
549     /**
550      * Gives up ownership of the memory if owned, or else clones it,
551      * copying the header and length T array items; resets itself to the internal memory.
552      * Returns NULL if the allocation failed.
553      * @param length number of T items to copy when cloning,
554      *        and array capacity of the clone when cloning
555      * @param resultCapacity will be set to the returned array's capacity (output-only)
556      * @return the header pointer;
557      *         caller becomes responsible for deleting the array
558      */
559     inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
560 private:
561     H *ptr;
562     int32_t capacity;
563     UBool needToRelease;
564     // stackHeader must precede stackArray immediately.
565     H stackHeader;
566     T stackArray[stackCapacity];
releaseMemory()567     void releaseMemory() {
568         if(needToRelease) {
569             uprv_free(ptr);
570         }
571     }
572     /* No comparison operators with other MaybeStackHeaderAndArray's. */
573     bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return FALSE;}
574     bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return TRUE;}
575     /* No ownership transfer: No copy constructor, no assignment operator. */
MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray &)576     MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {}
577     void operator=(const MaybeStackHeaderAndArray & /*other*/) {}
578 
579     // No heap allocation. Use only on the stack.
580     //   (Declaring these functions private triggers a cascade of problems;
581     //    see the MaybeStackArray class for details.)
582     // static void * U_EXPORT2 operator new(size_t size);
583     // static void * U_EXPORT2 operator new[](size_t size);
584 #if U_HAVE_PLACEMENT_NEW
585     // static void * U_EXPORT2 operator new(size_t, void *ptr);
586 #endif
587 };
588 
589 template<typename H, typename T, int32_t stackCapacity>
resize(int32_t newCapacity,int32_t length)590 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
591                                                                 int32_t length) {
592     if(newCapacity>=0) {
593 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
594       ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
595 #endif
596         H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
597         if(p!=NULL) {
598             if(length<0) {
599                 length=0;
600             } else if(length>0) {
601                 if(length>capacity) {
602                     length=capacity;
603                 }
604                 if(length>newCapacity) {
605                     length=newCapacity;
606                 }
607             }
608             uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
609             releaseMemory();
610             ptr=p;
611             capacity=newCapacity;
612             needToRelease=TRUE;
613         }
614         return p;
615     } else {
616         return NULL;
617     }
618 }
619 
620 template<typename H, typename T, int32_t stackCapacity>
orphanOrClone(int32_t length,int32_t & resultCapacity)621 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
622                                                                        int32_t &resultCapacity) {
623     H *p;
624     if(needToRelease) {
625         p=ptr;
626     } else {
627         if(length<0) {
628             length=0;
629         } else if(length>capacity) {
630             length=capacity;
631         }
632 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
633       ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
634 #endif
635         p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
636         if(p==NULL) {
637             return NULL;
638         }
639         uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
640     }
641     resultCapacity=length;
642     ptr=&stackHeader;
643     capacity=stackCapacity;
644     needToRelease=FALSE;
645     return p;
646 }
647 
648 U_NAMESPACE_END
649 
650 #endif  /* __cplusplus */
651 #endif  /* CMEMORY_H */
652