layer0/MemoryDebug.cpp (254 lines of code) (raw):
/*
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* Copyright (c) Schrodinger, LLC.
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information.
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-*
-*
-*
Z* -------------------------------------------------------------------
*/
/* This file can be compiled under C as a .c file, or under C++ as a .cc file*/
#include"os_predef.h"
#include"ov_port.h"
#include"MemoryDebug.h"
#include"MemoryCache.h"
#define GDB_ENTRY
void *MemoryReallocForSureSafe(void *ptr, unsigned int new_size, unsigned int old_size)
{
if(new_size < old_size) {
float *tmp = (float*) mmalloc(new_size);
if(tmp && new_size && old_size) {
memcpy(tmp, ptr, new_size);
}
FreeP(ptr);
return tmp;
} else {
return mrealloc(ptr, new_size);
}
}
void *MemoryReallocForSure(void *ptr, unsigned int new_size)
{ /* unsafe -- replace with above */
float *tmp = (float*) mmalloc(new_size);
if(tmp)
memcpy(tmp, ptr, new_size);
FreeP(ptr);
return tmp;
}
static void DieOutOfMemory(void)
{
printf
("****************************************************************************\n");
printf
("*** EEK! PyMOL just ran out of memory and crashed. To get around this, ***\n");
printf
("*** you may need to reduce the quality, size, or complexity of the scene ***\n");
printf
("*** that you are viewing or rendering. Sorry for the inconvenience... ***\n");
printf
("****************************************************************************\n");
#ifdef GDB_ENTRY
abort();
#endif
exit(EXIT_FAILURE);
}
void MemoryZero(char *p, char *q)
{
if(q - p)
memset(p, 0, q - p);
}
void *VLAExpand(void *ptr, ov_size rec)
{
VLARec *vla;
char *start, *stop;
unsigned int soffset = 0;
vla = &(((VLARec *) ptr)[-1]);
if(rec >= vla->size) {
if(vla->auto_zero)
soffset = sizeof(VLARec) + (vla->unit_size * vla->size);
vla->size = ((unsigned int) (rec * vla->grow_factor)) + 1;
#if 0
if(vla->size <= rec)
vla->size = rec + 1;
#endif
{
VLARec *old_vla = vla;
vla = (VLARec *) mrealloc(vla, (vla->unit_size * vla->size) + sizeof(VLARec));
while(!vla) { /* back off on the request size until it actually fits */
vla = old_vla;
vla->grow_factor = (vla->grow_factor - 1.0F) / 2.0F + 1.0F;
vla->size = ((unsigned int) (rec * vla->grow_factor)) + 1;
vla = (VLARec *) mrealloc(vla, (vla->unit_size * vla->size) + sizeof(VLARec));
if(!vla) {
if(old_vla->grow_factor < 1.001F) {
printf("VLAExpand-ERR: realloc failed.\n");
DieOutOfMemory();
}
}
}
}
if(vla->auto_zero) {
start = ((char *) vla) + soffset;
stop = ((char *) vla) + sizeof(VLARec) + (vla->unit_size * vla->size);
MemoryZero(start, stop);
}
}
return ((void *) &(vla[1]));
}
void *VLAMalloc(ov_size init_size, ov_size unit_size, unsigned int grow_factor,
int auto_zero)
{
VLARec *vla;
char *start, *stop;
vla = (VLARec*) mmalloc((init_size * unit_size) + sizeof(VLARec));
if(!vla) {
printf("VLAMalloc-ERR: malloc failed\n");
DieOutOfMemory();
}
vla->size = init_size;
vla->unit_size = unit_size;
vla->grow_factor = (1.0F + grow_factor * 0.1F);
vla->auto_zero = auto_zero;
if(vla->auto_zero) {
start = ((char *) vla) + sizeof(VLARec);
stop = ((char *) vla) + sizeof(VLARec) + (vla->unit_size * vla->size);
MemoryZero(start, stop);
}
return ((void *) &(vla[1]));
}
void VLAFree(void *ptr)
{
VLARec *vla;
if(!ptr) {
printf("VLAFree-ERR: tried to free NULL pointer!\n");
exit(EXIT_FAILURE);
}
vla = &(((VLARec *) ptr)[-1]);
mfree(vla);
}
unsigned int VLAGetSize(const void *ptr)
{
const VLARec *vla;
vla = &((VLARec *) ptr)[-1];
return (vla->size);
}
void *VLANewCopy(const void *ptr)
{
if(ptr) { /* NULL protected */
const VLARec *vla;
VLARec *new_vla;
unsigned int size;
vla = &((VLARec *) ptr)[-1];
size = (vla->unit_size * vla->size) + sizeof(VLARec);
new_vla = (VLARec*) mmalloc(size);
if(!new_vla) {
printf("VLACopy-ERR: mmalloc failed\n");
exit(EXIT_FAILURE);
} else {
memcpy(new_vla, vla, size);
}
return ((void *) &(new_vla[1]));
} else {
return NULL;
}
}
void *VLASetSize(void *ptr, unsigned int new_size)
{
VLARec *vla;
char *start = NULL;
char *stop;
unsigned int soffset = 0;
vla = &((VLARec *) ptr)[-1];
if(vla->auto_zero) {
soffset = sizeof(VLARec) + (vla->unit_size * vla->size);
}
vla->size = new_size;
vla = (VLARec*) mrealloc(vla, (vla->unit_size * vla->size) + sizeof(VLARec));
if(!vla) {
printf("VLASetSize-ERR: realloc failed.\n");
DieOutOfMemory();
}
if(vla->auto_zero) {
start = ((char *) vla) + soffset;
stop = ((char *) vla) + sizeof(VLARec) + (vla->unit_size * vla->size);
if(start < stop)
MemoryZero(start, stop);
}
return ((void *) &(vla[1]));
}
void *VLADeleteRaw(void *ptr, int index, unsigned int count)
{
if(ptr) {
VLARec *vla = ((VLARec *) ptr) - 1;
ov_size old_size = vla->size;
/* failsafe range-handling logic */
if(index<0) {
if(index < -old_size)
index = 0;
else
index = old_size + 1 + index;
if(index<0) index = 0;
}
if((count+index) > vla->size) {
count = vla->size - index;
}
if((index >= 0) && (count > 0) &&
(index < vla->size) && ((count + index) <= vla->size)) {
ov_size new_size = old_size - count;
ov_char *base = (ov_char *) ptr;
ov_os_memmove(base + index * vla->unit_size,
base + (count + index) * vla->unit_size,
((vla->size - index) - count) * vla->unit_size);
ptr = VLASetSize(ptr,new_size);
}
}
return ptr;
}
void *VLAInsertRaw(void *ptr, int index, unsigned int count)
{
if(ptr) {
VLARec *vla = ((VLARec *) ptr) - 1;
ov_size old_size = vla->size;
/* failsafe range-handling logic */
if(index<0) {
if(index < -old_size)
index = 0;
else
index = old_size + 1 + index;
if(index<0) index = 0;
}
if(index > old_size)
index = old_size;
if((index >= 0) && (count > 0) && (index <= old_size)) {
ov_int new_size = old_size + count;
ptr = VLASetSize(ptr,new_size);
if(ptr) {
ov_char *base = (ov_char *) ptr;
VLARec *vla = ((VLARec *) ptr) - 1;
ov_os_memmove(base + (index + count) * vla->unit_size,
base + index * vla->unit_size, (old_size - index) * vla->unit_size);
if(vla->auto_zero)
ov_os_memset(base + index * vla->unit_size, 0, vla->unit_size * count);
}
}
}
return ptr;
}
void *VLASetSizeForSure(void *ptr, unsigned int new_size)
{
VLARec *vla;
char *start = NULL;
char *stop;
unsigned int soffset = 0;
vla = &((VLARec *) ptr)[-1];
if(vla->auto_zero) {
soffset = sizeof(VLARec) + (vla->unit_size * vla->size);
}
if(new_size < vla->size) {
vla = (VLARec*) MemoryReallocForSureSafe(vla,
(vla->unit_size * new_size) + sizeof(VLARec),
(vla->unit_size * vla->size) + sizeof(VLARec));
vla->size = new_size;
} else {
vla->size = new_size;
vla = (VLARec*) mrealloc(vla, (vla->unit_size * vla->size) + sizeof(VLARec));
}
if(!vla) {
printf("VLASetSize-ERR: realloc failed.\n");
DieOutOfMemory();
}
if(vla->auto_zero) {
start = ((char *) vla) + soffset;
stop = ((char *) vla) + sizeof(VLARec) + (vla->unit_size * vla->size);
if(start < stop)
MemoryZero(start, stop);
}
return ((void *) &(vla[1]));
}