safemalloc.c 15.8 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000-2003 MySQL AB
unknown's avatar
unknown committed
2 3 4 5 6 7 8

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
unknown's avatar
unknown committed
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
unknown's avatar
unknown committed
10 11 12 13 14 15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
unknown's avatar
unknown committed
16 17 18 19

/*
 * Memory sub-system, written by Bjorn Benson
   Fixed to use my_sys scheme by Michael Widenius
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

  [This posting refers to an article entitled "oops, corrupted memory
  again!" in net.lang.c.  I am posting it here because it is source.]

  My tool for approaching this problem is to build another level of data
  abstraction on top of malloc() and free() that implements some checking.
  This does a number of things for you:
	- Checks for overruns and underruns on allocated data
	- Keeps track of where in the program the memory was malloc'ed
	- Reports on pieces of memory that were not free'ed
	- Records some statistics such as maximum memory used
	- Marks newly malloc'ed and newly free'ed memory with special values
  You can use this scheme to:
	- Find bugs such as overrun, underrun, etc because you know where
	  a piece of data was malloc'ed and where it was free'ed
	- Find bugs where memory was not free'ed
	- Find bugs where newly malloc'ed memory is used without initializing
	- Find bugs where newly free'ed memory is still used
	- Determine how much memory your program really uses
	- and other things

  To implement my scheme you must have a C compiler that has __LINE__ and
  __FILE__ macros.  If your compiler doesn't have these then (a) buy another:
  compilers that do are available on UNIX 4.2bsd based systems and the PC,
  and probably on other machines; or (b) change my scheme somehow.  I have
  recomendations on both these points if you would like them (e-mail please).

  There are 4 functions in my package:
	char *NEW( uSize )	Allocate memory of uSize bytes
				(equivalent to malloc())
	char *REA( pPtr, uSize) Allocate memory of uSize bytes, move data and
				free pPtr.
				(equivalent to realloc())
	FREE( pPtr )		Free memory allocated by NEW
				(equivalent to free())
	TERMINATE(file)		End system, report errors and stats on file
  I personally use two more functions, but have not included them here:
	char *STRSAVE( sPtr )	Save a copy of the string in dynamic memory
	char *RENEW( pPtr, uSize )
				(equivalent to realloc())

*/
unknown's avatar
unknown committed
62 63 64 65 66 67 68 69 70 71

#ifndef SAFEMALLOC
#define SAFEMALLOC			/* Get protos from my_sys */
#endif

#include "mysys_priv.h"
#include <m_string.h>
#include "my_static.h"
#include "mysys_err.h"

72
ulonglong sf_malloc_mem_limit= ~(ulonglong)0;
unknown's avatar
unknown committed
73

74
#ifndef PEDANTIC_SAFEMALLOC
75
/*
76
  Set to 1 after TERMINATE() if we had to fiddle with sf_malloc_count and
77 78 79
  the linked list of blocks so that _sanity() will not fuss when it
  is not supposed to
*/
unknown's avatar
unknown committed
80
static int sf_malloc_tampered= 0;
81 82 83
#endif
				   

unknown's avatar
unknown committed
84 85 86 87
	/* Static functions prototypes */

static int check_ptr(const char *where, byte *ptr, const char *sFile,
		     uint uLine);
88
static int _checkchunk(struct st_irem *pRec, const char *sFile, uint uLine);
unknown's avatar
unknown committed
89 90

/*
unknown's avatar
unknown committed
91 92
  Note: We only fill up the allocated block. This do not include
  malloc() roundoff or the extra space required by the irem
93 94
  structures.
*/
unknown's avatar
unknown committed
95

96 97 98 99 100 101 102 103 104 105
/*
  NEW'ed memory is filled with this value so that references to it will
  end up being very strange.
*/
#define ALLOC_VAL	(uchar) 0xA5
/*
  FEEE'ed memory is filled with this value so that references to it will
  end up being very strange.
*/
#define FREE_VAL	(uchar) 0x8F
unknown's avatar
unknown committed
106
#define MAGICKEY	0x14235296	/* A magic value for underrun key */
107 108 109 110 111 112 113 114

/*
  Warning: do not change the MAGICEND? values to something with the
  high bit set.  Various C compilers (like the 4.2bsd one) do not do
  the sign extension right later on in this code and you will get
  erroneous errors.
*/

unknown's avatar
unknown committed
115 116 117 118 119 120
#define MAGICEND0	0x68		/* Magic values for overrun keys  */
#define MAGICEND1	0x34		/*		"		  */
#define MAGICEND2	0x7A		/*		"		  */
#define MAGICEND3	0x15		/*		"		  */


121
/* Allocate some memory. */
unknown's avatar
unknown committed
122

123
gptr _mymalloc(uint size, const char *filename, uint lineno, myf MyFlags)
unknown's avatar
unknown committed
124
{
125 126
  struct st_irem *irem;
  char *data;
unknown's avatar
unknown committed
127
  DBUG_ENTER("_mymalloc");
128
  DBUG_PRINT("enter",("Size: %u",size));
unknown's avatar
unknown committed
129

unknown's avatar
unknown committed
130
  if (!sf_malloc_quick)
131
    (void) _sanity (filename, lineno);
unknown's avatar
unknown committed
132

133 134
  if (size + sf_malloc_cur_memory > sf_malloc_mem_limit)
    irem= 0;
unknown's avatar
unknown committed
135 136 137
  else
  {
    /* Allocate the physical memory */
138 139 140 141 142
    irem= (struct st_irem *) malloc (ALIGN_SIZE(sizeof(struct st_irem)) +
				     sf_malloc_prehunc +
				     size +	/* size requested */
				     4 +	/* overrun mark */
				     sf_malloc_endhunc);
unknown's avatar
unknown committed
143 144
  }
  /* Check if there isn't anymore memory avaiable */
145
  if (!irem)
unknown's avatar
unknown committed
146 147 148 149
  {
    if (MyFlags & MY_FAE)
      error_handler_hook=fatal_error_handler_hook;
    if (MyFlags & (MY_FAE+MY_WME))
unknown's avatar
unknown committed
150
    {
unknown's avatar
unknown committed
151 152
      char buff[SC_MAXWIDTH];
      my_errno=errno;
153
      sprintf(buff,"Out of memory at line %d, '%s'", lineno, filename);
unknown's avatar
unknown committed
154 155
      my_message(EE_OUTOFMEMORY,buff,MYF(ME_BELL+ME_WAITTANG));
      sprintf(buff,"needed %d byte (%ldk), memory in use: %ld bytes (%ldk)",
156 157
	      size, (size + 1023L) / 1024L,
	      sf_malloc_max_memory, (sf_malloc_max_memory + 1023L) / 1024L);
unknown's avatar
unknown committed
158
      my_message(EE_OUTOFMEMORY,buff,MYF(ME_BELL+ME_WAITTANG));
unknown's avatar
unknown committed
159
    }
unknown's avatar
unknown committed
160
    DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'",
161
			sf_malloc_max_memory,lineno, filename));
unknown's avatar
unknown committed
162 163
    if (MyFlags & MY_FAE)
      exit(1);
164
    DBUG_RETURN ((gptr) 0);
unknown's avatar
unknown committed
165
  }
unknown's avatar
unknown committed
166

unknown's avatar
unknown committed
167
  /* Fill up the structure */
168 169 170 171 172 173 174 175 176 177 178
  data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) +
	 sf_malloc_prehunc);
  *((uint32*) (data-sizeof(uint32)))= MAGICKEY;
  data[size + 0]= MAGICEND0;
  data[size + 1]= MAGICEND1;
  data[size + 2]= MAGICEND2;
  data[size + 3]= MAGICEND3;
  irem->filename= (my_string) filename;
  irem->linenum= lineno;
  irem->datasize= size;
  irem->prev=	  NULL;
unknown's avatar
unknown committed
179 180 181

  /* Add this remember structure to the linked list */
  pthread_mutex_lock(&THR_LOCK_malloc);
182 183 184
  if ((irem->next= sf_malloc_root))
    sf_malloc_root->prev= irem;
  sf_malloc_root= irem;
unknown's avatar
unknown committed
185 186

  /* Keep the statistics */
187 188 189 190
  sf_malloc_cur_memory+= size;
  if (sf_malloc_cur_memory > sf_malloc_max_memory)
    sf_malloc_max_memory= sf_malloc_cur_memory;
  sf_malloc_count++;
unknown's avatar
unknown committed
191
  pthread_mutex_unlock(&THR_LOCK_malloc);
unknown's avatar
unknown committed
192

unknown's avatar
unknown committed
193 194
  /* Set the memory to the aribtrary wierd value */
  if ((MyFlags & MY_ZEROFILL) || !sf_malloc_quick)
195
    bfill(data, size, (char) (MyFlags & MY_ZEROFILL ? 0 : ALLOC_VAL));
unknown's avatar
unknown committed
196
  /* Return a pointer to the real data */
197
  DBUG_PRINT("exit",("ptr: 0x%lx", data));
198 199 200 201 202
  if (sf_min_adress > data)
    sf_min_adress= data;
  if (sf_max_adress < data)
    sf_max_adress= data;
  DBUG_RETURN ((gptr) data);
unknown's avatar
unknown committed
203 204
}

205

unknown's avatar
unknown committed
206
/*
207 208 209
  Allocate some new memory and move old memoryblock there.
  Free then old memoryblock
*/
unknown's avatar
unknown committed
210

211 212
gptr _myrealloc(register gptr ptr, register uint size,
		const char *filename, uint lineno, myf MyFlags)
unknown's avatar
unknown committed
213
{
214 215
  struct st_irem *irem;
  char *data;
unknown's avatar
unknown committed
216 217
  DBUG_ENTER("_myrealloc");

218 219
  if (!ptr && (MyFlags & MY_ALLOW_ZERO_PTR))
    DBUG_RETURN(_mymalloc(size, filename, lineno, MyFlags));
unknown's avatar
unknown committed
220 221

  if (!sf_malloc_quick)
222
    (void) _sanity (filename, lineno);
unknown's avatar
unknown committed
223

224
  if (check_ptr("Reallocating", (byte*) ptr, filename, lineno))
unknown's avatar
unknown committed
225 226
    DBUG_RETURN((gptr) NULL);

227 228 229
  irem= (struct st_irem *) (((char*) ptr) - ALIGN_SIZE(sizeof(struct st_irem))-
			    sf_malloc_prehunc);
  if (*((uint32*) (((char*) ptr)- sizeof(uint32))) != MAGICKEY)
unknown's avatar
unknown committed
230
  {
unknown's avatar
unknown committed
231
    fprintf(stderr, "Error: Reallocating unallocated data at line %d, '%s'\n",
232
	    lineno, filename);
unknown's avatar
unknown committed
233
    DBUG_PRINT("safe",("Reallocating unallocated data at line %d, '%s'",
234
		       lineno, filename));
unknown's avatar
unknown committed
235 236 237 238
    (void) fflush(stderr);
    DBUG_RETURN((gptr) NULL);
  }

239
  if ((data= _mymalloc(size,filename,lineno,MyFlags))) /* Allocate new area */
unknown's avatar
unknown committed
240
  {
241 242 243
    size=min(size, irem->datasize);		/* Move as much as possibly */
    memcpy((byte*) data, ptr, (size_t) size);	/* Copy old data */
    _myfree(ptr, filename, lineno, 0);		/* Free not needed area */
unknown's avatar
unknown committed
244 245 246 247
  }
  else
  {
    if (MyFlags & MY_HOLD_ON_ERROR)
248
      DBUG_RETURN(ptr);
unknown's avatar
unknown committed
249
    if (MyFlags & MY_FREE_ON_ERROR)
250
      _myfree(ptr, filename, lineno, 0);
unknown's avatar
unknown committed
251
  }
252
  DBUG_RETURN(data);
unknown's avatar
unknown committed
253 254 255
} /* _myrealloc */


256
/* Deallocate some memory. */
unknown's avatar
unknown committed
257

258
void _myfree(gptr ptr, const char *filename, uint lineno, myf myflags)
unknown's avatar
unknown committed
259
{
260
  struct st_irem *irem;
unknown's avatar
unknown committed
261
  DBUG_ENTER("_myfree");
262
  DBUG_PRINT("enter",("ptr: 0x%lx", ptr));
unknown's avatar
unknown committed
263 264

  if (!sf_malloc_quick)
265
    (void) _sanity (filename, lineno);
unknown's avatar
unknown committed
266

267 268
  if ((!ptr && (myflags & MY_ALLOW_ZERO_PTR)) ||
      check_ptr("Freeing",(byte*) ptr,filename,lineno))
unknown's avatar
unknown committed
269 270 271
    DBUG_VOID_RETURN;

  /* Calculate the address of the remember structure */
272 273
  irem= (struct st_irem *) ((char*) ptr- ALIGN_SIZE(sizeof(struct st_irem))-
			    sf_malloc_prehunc);
unknown's avatar
unknown committed
274

275 276 277
  /*
    Check to make sure that we have a real remember structure.
    Note: this test could fail for four reasons:
unknown's avatar
unknown committed
278 279 280 281
    (1) The memory was already free'ed
    (2) The memory was never new'ed
    (3) There was an underrun
    (4) A stray pointer hit this location
282
  */
unknown's avatar
unknown committed
283

284
  if (*((uint32*) ((char*) ptr- sizeof(uint32))) != MAGICKEY)
unknown's avatar
unknown committed
285
  {
unknown's avatar
unknown committed
286
    fprintf(stderr, "Error: Freeing unallocated data at line %d, '%s'\n",
287 288
	    lineno, filename);
    DBUG_PRINT("safe",("Unallocated data at line %d, '%s'",lineno,filename));
unknown's avatar
unknown committed
289 290 291 292 293 294
    (void) fflush(stderr);
    DBUG_VOID_RETURN;
  }

  /* Remove this structure from the linked list */
  pthread_mutex_lock(&THR_LOCK_malloc);
295 296
  if (irem->prev)
    irem->prev->next= irem->next;
unknown's avatar
unknown committed
297
   else
298
    sf_malloc_root= irem->next;
unknown's avatar
unknown committed
299

300 301
  if (irem->next)
    irem->next->prev= irem->prev;
unknown's avatar
unknown committed
302
  /* Handle the statistics */
303 304
  sf_malloc_cur_memory-= irem->datasize;
  sf_malloc_count--;
unknown's avatar
unknown committed
305 306 307 308
  pthread_mutex_unlock(&THR_LOCK_malloc);

#ifndef HAVE_purify
  /* Mark this data as free'ed */
309
  if (!sf_malloc_quick)
310
    bfill(ptr, irem->datasize, (pchar) FREE_VAL);
unknown's avatar
unknown committed
311
#endif
312
  *((uint32*) ((char*) ptr- sizeof(uint32)))= ~MAGICKEY;
unknown's avatar
unknown committed
313
  /* Actually free the memory */
314
  free((char*) irem);
unknown's avatar
unknown committed
315 316 317 318 319
  DBUG_VOID_RETURN;
}

	/* Check if we have a wrong  pointer */

320 321
static int check_ptr(const char *where, byte *ptr, const char *filename,
		     uint lineno)
unknown's avatar
unknown committed
322 323 324
{
  if (!ptr)
  {
unknown's avatar
unknown committed
325
    fprintf(stderr, "Error: %s NULL pointer at line %d, '%s'\n",
326 327
	    where,lineno, filename);
    DBUG_PRINT("safe",("Null pointer at line %d '%s'", lineno, filename));
unknown's avatar
unknown committed
328 329 330 331
    (void) fflush(stderr);
    return 1;
  }
#ifndef _MSC_VER
332
  if ((long) ptr & (ALIGN_SIZE(1)-1))
unknown's avatar
unknown committed
333
  {
unknown's avatar
unknown committed
334
    fprintf(stderr, "Error: %s wrong aligned pointer at line %d, '%s'\n",
335
	    where,lineno, filename);
unknown's avatar
unknown committed
336
    DBUG_PRINT("safe",("Wrong aligned pointer at line %d, '%s'",
337
		       lineno,filename));
unknown's avatar
unknown committed
338 339 340 341 342 343
    (void) fflush(stderr);
    return 1;
  }
#endif
  if (ptr < sf_min_adress || ptr > sf_max_adress)
  {
unknown's avatar
unknown committed
344
    fprintf(stderr, "Error: %s pointer out of range at line %d, '%s'\n",
345
	    where,lineno, filename);
unknown's avatar
unknown committed
346
    DBUG_PRINT("safe",("Pointer out of range at line %d '%s'",
347
		       lineno,filename));
unknown's avatar
unknown committed
348 349 350 351 352 353
    (void) fflush(stderr);
    return 1;
  }
  return 0;
}

unknown's avatar
unknown committed
354

unknown's avatar
unknown committed
355
/*
356 357 358
  TERMINATE(FILE *file)
    Report on all the memory pieces that have not been
    free'ed as well as the statistics.
unknown's avatar
unknown committed
359 360
 */

unknown's avatar
unknown committed
361
void TERMINATE(FILE *file)
unknown's avatar
unknown committed
362
{
363
  struct st_irem *irem;
unknown's avatar
unknown committed
364 365 366
  DBUG_ENTER("TERMINATE");
  pthread_mutex_lock(&THR_LOCK_malloc);

367 368 369 370 371
  /*
    Report the difference between number of calls to
    NEW and the number of calls to FREE.  >0 means more
    NEWs than FREEs.  <0, etc.
  */
unknown's avatar
unknown committed
372

373
  if (sf_malloc_count)
unknown's avatar
unknown committed
374 375 376
  {
    if (file)
    {
377
      fprintf(file, "Warning: Not freed memory segments: %u\n",
378
	      sf_malloc_count);
unknown's avatar
unknown committed
379 380
      (void) fflush(file);
    }
381
    DBUG_PRINT("safe",("sf_malloc_count: %u", sf_malloc_count));
unknown's avatar
unknown committed
382 383
  }

384 385 386 387
  /*
    Report on all the memory that was allocated with NEW
    but not free'ed with FREE.
  */
unknown's avatar
unknown committed
388

389
  if ((irem= sf_malloc_root))
unknown's avatar
unknown committed
390 391 392
  {
    if (file)
    {
unknown's avatar
unknown committed
393
      fprintf(file, "Warning: Memory that was not free'ed (%ld bytes):\n",
394
	      sf_malloc_cur_memory);
unknown's avatar
unknown committed
395 396
      (void) fflush(file);
    }
397 398 399
    DBUG_PRINT("safe",("Memory that was not free'ed (%ld bytes):",
		       sf_malloc_cur_memory));
    while (irem)
unknown's avatar
unknown committed
400
    {
401 402
      char *data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) +
		   sf_malloc_prehunc);
unknown's avatar
unknown committed
403 404
      if (file)
      {
unknown's avatar
unknown committed
405 406
	fprintf(file,
		"\t%6u bytes at 0x%09lx, allocated at line %4u in '%s'",
407
		irem->datasize, (long) data, irem->linenum, irem->filename);
408
	fprintf(file, "\n");
unknown's avatar
unknown committed
409 410 411 412
	(void) fflush(file);
      }
      DBUG_PRINT("safe",
		 ("%6u bytes at 0x%09lx, allocated at line %4d in '%s'",
413 414
		  irem->datasize, data, irem->linenum, irem->filename));
      irem= irem->next;
unknown's avatar
unknown committed
415 416 417 418 419
    }
  }
  /* Report the memory usage statistics */
  if (file)
  {
unknown's avatar
unknown committed
420
    fprintf(file, "Maximum memory usage: %ld bytes (%ldk)\n",
421
	    sf_malloc_max_memory, (sf_malloc_max_memory + 1023L) / 1024L);
unknown's avatar
unknown committed
422 423 424
    (void) fflush(file);
  }
  DBUG_PRINT("safe",("Maximum memory usage: %ld bytes (%ldk)",
425 426
		     sf_malloc_max_memory, (sf_malloc_max_memory + 1023L) /
		     1024L));
unknown's avatar
unknown committed
427 428 429 430 431 432 433
  pthread_mutex_unlock(&THR_LOCK_malloc);
  DBUG_VOID_RETURN;
}


	/* Returns 0 if chunk is ok */

434 435
static int _checkchunk(register struct st_irem *irem, const char *filename,
		       uint lineno)
unknown's avatar
unknown committed
436
{
437 438
  int flag=0;
  char *magicp, *data;
unknown's avatar
unknown committed
439

440 441
  data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) +
	 sf_malloc_prehunc);
unknown's avatar
unknown committed
442
  /* Check for a possible underrun */
443
  if (*((uint32*) (data- sizeof(uint32))) != MAGICKEY)
unknown's avatar
unknown committed
444
  {
unknown's avatar
unknown committed
445
    fprintf(stderr, "Error: Memory allocated at %s:%d was underrun,",
446 447
	    irem->filename, irem->linenum);
    fprintf(stderr, " discovered at %s:%d\n", filename, lineno);
unknown's avatar
unknown committed
448
    (void) fflush(stderr);
449
    DBUG_PRINT("safe",("Underrun at 0x%lx, allocated at %s:%d",
450
		       data, irem->filename, irem->linenum));
unknown's avatar
unknown committed
451 452 453 454
    flag=1;
  }

  /* Check for a possible overrun */
455
  magicp= data + irem->datasize;
unknown's avatar
unknown committed
456 457 458 459 460
  if (*magicp++ != MAGICEND0 ||
      *magicp++ != MAGICEND1 ||
      *magicp++ != MAGICEND2 ||
      *magicp++ != MAGICEND3)
  {
unknown's avatar
unknown committed
461
    fprintf(stderr, "Error: Memory allocated at %s:%d was overrun,",
462 463
	    irem->filename, irem->linenum);
    fprintf(stderr, " discovered at '%s:%d'\n", filename, lineno);
unknown's avatar
unknown committed
464
    (void) fflush(stderr);
465
    DBUG_PRINT("safe",("Overrun at 0x%lx, allocated at %s:%d",
466 467 468
		       data,
		       irem->filename,
		       irem->linenum));
unknown's avatar
unknown committed
469 470 471 472 473 474 475 476
    flag=1;
  }
  return(flag);
}


	/* Returns how many wrong chunks */

477
int _sanity(const char *filename, uint lineno)
unknown's avatar
unknown committed
478
{
479
  reg1 struct st_irem *irem;
unknown's avatar
unknown committed
480 481 482 483
  reg2 int flag=0;
  uint count=0;

  pthread_mutex_lock(&THR_LOCK_malloc);
484
#ifndef PEDANTIC_SAFEMALLOC  
485
  if (sf_malloc_tampered && (int) sf_malloc_count < 0)
486
    sf_malloc_count=0;
487
#endif  
488 489 490
  count=sf_malloc_count;
  for (irem= sf_malloc_root; irem != NULL && count-- ; irem= irem->next)
    flag+= _checkchunk (irem, filename, lineno);
unknown's avatar
unknown committed
491
  pthread_mutex_unlock(&THR_LOCK_malloc);
492
  if (count || irem)
unknown's avatar
unknown committed
493
  {
unknown's avatar
unknown committed
494
    const char *format="Error: Safemalloc link list destroyed, discovered at '%s:%d'";
495 496
    fprintf(stderr, format, filename, lineno); fputc('\n',stderr);
    fprintf(stderr, "root=%p,count=%d,irem=%p\n", sf_malloc_root,count,irem);
unknown's avatar
unknown committed
497
    (void) fflush(stderr);
498
    DBUG_PRINT("safe",(format, filename, lineno));
unknown's avatar
unknown committed
499 500 501 502 503 504 505 506
    flag=1;
  }
  return flag;
} /* _sanity */


	/* malloc and copy */

507 508
gptr _my_memdup(const byte *from, uint length, const char *filename,
		uint lineno, myf MyFlags)
unknown's avatar
unknown committed
509 510
{
  gptr ptr;
511
  if ((ptr=_mymalloc(length,filename,lineno,MyFlags)) != 0)
unknown's avatar
unknown committed
512 513 514 515 516
    memcpy((byte*) ptr, (byte*) from,(size_t) length);
  return(ptr);
} /*_my_memdup */


517
char *_my_strdup(const char *from, const char *filename, uint lineno,
518
		 myf MyFlags)
unknown's avatar
unknown committed
519 520 521
{
  gptr ptr;
  uint length=(uint) strlen(from)+1;
522
  if ((ptr=_mymalloc(length,filename,lineno,MyFlags)) != 0)
unknown's avatar
unknown committed
523
    memcpy((byte*) ptr, (byte*) from,(size_t) length);
524
  return((char*) ptr);
unknown's avatar
unknown committed
525
} /* _my_strdup */
unknown's avatar
unknown committed
526 527


528
char *_my_strdup_with_length(const byte *from, uint length,
529
			     const char *filename, uint lineno,
530
			     myf MyFlags)
unknown's avatar
unknown committed
531 532
{
  gptr ptr;
533
  if ((ptr=_mymalloc(length+1,filename,lineno,MyFlags)) != 0)
unknown's avatar
unknown committed
534 535 536 537
  {
    memcpy((byte*) ptr, (byte*) from,(size_t) length);
    ptr[length]=0;
  }
538
  return((char *) ptr);
unknown's avatar
unknown committed
539
}