提交 e7bdf0c2 编写于 作者: weixin_48148422's avatar weixin_48148422

support other alloc mode

上级 fc6737ab
...@@ -125,11 +125,9 @@ IF (NOT DEFINED TD_CLUSTER) ...@@ -125,11 +125,9 @@ IF (NOT DEFINED TD_CLUSTER)
# debug flag # debug flag
# #
# ADD_DEFINITIONS(-D_CHECK_HEADER_FILE_) # ADD_DEFINITIONS(-D_CHECK_HEADER_FILE_)
IF (${MEM_CHECK} MATCHES "true")
# TAOS_MEM_CHECK ADD_DEFINITIONS(-DTAOS_MEM_CHECK)
# 1 to test memory allocation failure ENDIF ()
# 2 to check memory leak
ADD_DEFINITIONS(-DTAOS_MEM_CHECK=2)
IF (TD_CLUSTER) IF (TD_CLUSTER)
ADD_DEFINITIONS(-DCLUSTER) ADD_DEFINITIONS(-DCLUSTER)
......
...@@ -14,8 +14,8 @@ extern "C" { ...@@ -14,8 +14,8 @@ extern "C" {
* Method: * Method:
* Signature: (Ljava/lang/String;)V * Signature: (Ljava/lang/String;)V
*/ */
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_detectMemoryLeakImp JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp
(JNIEnv *, jclass, jstring, jboolean); (JNIEnv *, jclass, jint, jstring, jboolean);
/* /*
* Class: com_taosdata_jdbc_TSDBJNIConnector * Class: com_taosdata_jdbc_TSDBJNIConnector
......
...@@ -111,21 +111,18 @@ void jniGetGlobalMethod(JNIEnv *env) { ...@@ -111,21 +111,18 @@ void jniGetGlobalMethod(JNIEnv *env) {
jniTrace("native method register finished"); jniTrace("native method register finished");
} }
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_detectMemoryLeakImp(JNIEnv *env, jobject jobj, jstring jPath, jboolean jAutoDump) { JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp(JNIEnv *env, jobject jobj, jint jMode, jstring jPath, jboolean jAutoDump) {
if (jPath != NULL) { if (jPath != NULL) {
const char *path = (*env)->GetStringUTFChars(env, jPath, NULL); const char *path = (*env)->GetStringUTFChars(env, jPath, NULL);
taos_detect_memory_leak(path, !!jAutoDump); taosSetAllocMode(jMode, path, !!jAutoDump);
(*env)->ReleaseStringUTFChars(env, jPath, path); (*env)->ReleaseStringUTFChars(env, jPath, path);
} else { } else {
taos_detect_memory_leak(NULL, !!jAutoDump); taosSetAllocMode(jMode, NULL, !!jAutoDump);
} }
jniGetGlobalMethod(env);
} }
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_dumpMemoryLeakImp(JNIEnv *env, jobject jobj) { JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_dumpMemoryLeakImp(JNIEnv *env, jobject jobj) {
taos_dump_memory_leak(); taosDumpMemoryLeak();
jniGetGlobalMethod(env);
} }
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *env, jobject jobj, jstring jconfigDir) { JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *env, jobject jobj, jstring jconfigDir) {
......
...@@ -187,44 +187,35 @@ static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, unsigned int inLen, cha ...@@ -187,44 +187,35 @@ static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, unsigned int inLen, cha
char *taosIpStr(uint32_t ipInt); char *taosIpStr(uint32_t ipInt);
extern void taos_detect_memory_leak(const char* path, bool autoDump); #define TAOS_ALLOC_MODE_DEFAULT 0
extern void taos_dump_memory_leak(); #define TAOS_ALLOC_MODE_RANDOM_FAIL 1
#define TAOS_ALLOC_MODE_DETECT_LEAK 2
#if TAOS_MEM_CHECK == 1 void taosSetAllocMode(int mode, const char* path, bool autoDump);
void taosDumpMemoryLeak();
// Use during test to simulate the success and failure scenarios of memory allocation
extern void* taos_malloc(size_t size, const char* func); #ifdef TAOS_MEM_CHECK
extern void* taos_calloc(size_t num, size_t size, const char* func);
extern void* taos_realloc(void* ptr, size_t size, const char* func); void * taos_malloc(size_t size, const char *file, uint32_t line);
extern void taos_free(void* ptr); void * taos_calloc(size_t num, size_t size, const char *file, uint32_t line);
extern char* taos_strdup(const char* str, const char* func); void * taos_realloc(void *ptr, size_t size, const char *file, uint32_t line);
extern char* taos_strndup(const char* str, size_t size, const char* func); void taos_free(void *ptr, const char *file, uint32_t line);
#define malloc(size) taos_malloc(size, __FUNCTION__) char * taos_strdup(const char *str, const char *file, uint32_t line);
#define calloc(num, size) taos_calloc(num, size, __FUNCTION__) char * taos_strndup(const char *str, size_t size, const char *file, uint32_t line);
#define realloc(ptr, size) taos_realloc(ptr, size, __FUNCTION__) ssize_t taos_getline(char **lineptr, size_t *n, FILE *stream, const char *file, uint32_t line);
#define free(ptr) taos_free(ptr)
#define strdup(str) taos_strdup(str, __FUNCTION__) #ifndef TAOS_MEM_CHECK_IMPL
#define strndup(str, size) taos_strndup(str, size, __FUNCTION__)
#define malloc(size) taos_malloc(size, __FILE__, __LINE__)
#elif TAOS_MEM_CHECK == 2 #define calloc(num, size) taos_calloc(num, size, __FILE__, __LINE__)
#define realloc(ptr, size) taos_realloc(ptr, size, __FILE__, __LINE__)
extern void* taos_malloc(size_t size, const char* file, uint32_t line); #define free(ptr) taos_free(ptr, __FILE__, __LINE__)
extern void* taos_calloc(size_t num, size_t size, const char* file, uint32_t line); #define strdup(str) taos_strdup(str, __FILE__, __LINE__)
extern void* taos_realloc(void* ptr, size_t size, const char* file, uint32_t line); #define strndup(str, size) taos_strndup(str, size, __FILE__, __LINE__)
extern void taos_free(void* ptr, const char* file, uint32_t line);
extern char* taos_strdup(const char* str, const char* file, uint32_t line);
extern char* taos_strndup(const char* str, size_t size, const char* file, uint32_t line);
extern ssize_t taos_getline(char **lineptr, size_t *n, FILE *stream, const char* file, uint32_t line);
#define malloc(size) taos_malloc(size, __FILE__, __LINE__)
#define calloc(num, size) taos_calloc(num, size, __FILE__, __LINE__)
#define realloc(ptr, size) taos_realloc(ptr, size, __FILE__, __LINE__)
#define free(ptr) taos_free(ptr, __FILE__, __LINE__)
#define strdup(str) taos_strdup(str, __FILE__, __LINE__)
#define strndup(str, size) taos_strndup(str, size, __FILE__, __LINE__)
#define getline(lineptr, n, stream) taos_getline(lineptr, n, stream, __FILE__, __LINE__) #define getline(lineptr, n, stream) taos_getline(lineptr, n, stream, __FILE__, __LINE__)
#endif #endif // TAOS_MEM_CHECK_IMPL
#endif // TAOS_MEM_CHECK
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -61,12 +61,18 @@ int main(int argc, char *argv[]) { ...@@ -61,12 +61,18 @@ int main(int argc, char *argv[]) {
return 0; return 0;
} else if (strcmp(argv[i], "-k") == 0) { } else if (strcmp(argv[i], "-k") == 0) {
dnodeParseParameterK(); dnodeParseParameterK();
#if TAOS_MEM_CHECK == 2 #ifdef TAOS_MEM_CHECK
} else if (strcmp(argv[i], "--check-mem-leak") == 0) { } else if (strcmp(argv[i], "--alloc-random-fail") == 0) {
if ((i < argc - 1) && (argv[i+1][0] != '-')) { if ((i < argc - 1) && (argv[i+1][0] != '-')) {
taos_detect_memory_leak(argv[++i], true); taosSetAllocMode(TAOS_ALLOC_MODE_RANDOM_FAIL, argv[++i], true);
} else { } else {
taos_detect_memory_leak(NULL, true); taosSetAllocMode(TAOS_ALLOC_MODE_RANDOM_FAIL, NULL, true);
}
} else if (strcmp(argv[i], "--detect-mem-leak") == 0) {
if ((i < argc - 1) && (argv[i+1][0] != '-')) {
taosSetAllocMode(TAOS_ALLOC_MODE_DETECT_LEAK, argv[++i], true);
} else {
taosSetAllocMode(TAOS_ALLOC_MODE_DETECT_LEAK, NULL, true);
} }
#endif #endif
} }
......
...@@ -15,72 +15,75 @@ ...@@ -15,72 +15,75 @@
#include "os.h" #include "os.h"
#include "tlog.h" #include "tlog.h"
#include "os.h"
#if TAOS_MEM_CHECK == 1 #define TAOS_MEM_CHECK_IMPL
#include "tutil.h"
#ifdef TAOS_MEM_CHECK
static int allocMode = TAOS_ALLOC_MODE_DEFAULT;
static FILE* fpAllocLog = NULL;
////////////////////////////////////////////////////////////////////////////////
// memory allocator which fails randomly
extern int32_t taosGetTimestampSec(); extern int32_t taosGetTimestampSec();
static int32_t startTime = 0; static int32_t startTime = INT32_MAX;;
static int64_t m_curLimit = 100 * 1024;
static bool isMallocMem(size_t size, const char* func) { static bool random_alloc_fail(size_t size, const char* file, uint32_t line) {
if (0 == startTime) { if (taosGetTimestampSec() < startTime) {
startTime = taosGetTimestampSec(); return false;
return true;
} else {
int32_t currentTime = taosGetTimestampSec();
if (currentTime - startTime < 10) return true;
} }
if (size > m_curLimit) { if (size < 100 * (size_t)1024) {
if (3 == rand() % 20) { return false;
pTrace("====no alloc mem in func: %s, size:%d", func, size);
return false;
}
} }
return true; if (rand() % 20 != 0) {
} return false;
}
void* taos_malloc(size_t size, const char* func) { if (fpAllocLog != NULL) {
if (false == isMallocMem(size, func)) { fprintf(fpAllocLog, "memory allocation(%zu bytes) at line %d of '%s' will fail.\n", size, line, file);
return NULL;
} }
return malloc(size);
return true;
} }
void* taos_calloc(size_t num, size_t size, const char* func) { static void* malloc_random(size_t size, const char* file, uint32_t line) {
if (false == isMallocMem(size, func)) { return random_alloc_fail(size, file, line) ? NULL : malloc(size);
return NULL;
}
return calloc(num, size);
} }
void* taos_realloc(void* ptr, size_t size, const char* func) { static void* calloc_random(size_t num, size_t size, const char* file, uint32_t line) {
if (false == isMallocMem(size, func)) { return random_alloc_fail(num * size, file, line) ? NULL : calloc(num, size);
return NULL;
}
return realloc(ptr, size);
} }
void taos_free(void* ptr) { free(ptr); } static void* realloc_random(void* ptr, size_t size, const char* file, uint32_t line) {
return random_alloc_fail(size, file, line) ? NULL : realloc(ptr, size);
}
char* taos_strdup(const char* str, const char* func) { static char* strdup_random(const char* str, const char* file, uint32_t line) {
size_t len = strlen(str); size_t len = strlen(str);
return isMallocMem(len + 1, func) ? strdup(str) : NULL; return random_alloc_fail(len + 1, file, line) ? NULL : strdup(str);
} }
char* taos_strndup(const char* str, size_t size, const char* func) { static char* strndup_random(const char* str, size_t size, const char* file, uint32_t line) {
size_t len = strlen(str); size_t len = strlen(str);
if (len > size) { if (len > size) {
len = size; len = size;
} }
return isMallocMem(len + 1, func) ? strndup(str, len) : NULL; return random_alloc_fail(len + 1, file, line) ? NULL : strndup(str, len);
}
static ssize_t getline_random(char **lineptr, size_t *n, FILE *stream, const char* file, uint32_t line) {
return random_alloc_fail(*n, file, line) ? -1 : getline(lineptr, n, stream);
} }
#elif TAOS_MEM_CHECK == 2 ////////////////////////////////////////////////////////////////////////////////
// memory allocator with leak detection
#define MAGIC 0x55AA #define MEMBLK_MAGIC 0x55AA
typedef struct SMemBlock { typedef struct SMemBlock {
const char* file; const char* file;
...@@ -95,7 +98,6 @@ typedef struct SMemBlock { ...@@ -95,7 +98,6 @@ typedef struct SMemBlock {
static SMemBlock *blocks = NULL; static SMemBlock *blocks = NULL;
static uintptr_t lock = 0; static uintptr_t lock = 0;
static FILE* fpMemLeak = NULL;
static void add_mem_block(SMemBlock* blk) { static void add_mem_block(SMemBlock* blk) {
blk->prev = NULL; blk->prev = NULL;
...@@ -127,7 +129,25 @@ static void remove_mem_block(SMemBlock* blk) { ...@@ -127,7 +129,25 @@ static void remove_mem_block(SMemBlock* blk) {
blk->next = NULL; blk->next = NULL;
} }
void* taos_malloc(size_t size, const char* file, uint32_t line) { static void free_detect_leak(void* ptr, const char* file, uint32_t line) {
if (ptr == NULL) {
return;
}
SMemBlock* blk = (SMemBlock*)(((char*)ptr) - sizeof(SMemBlock));
if (blk->magic != MEMBLK_MAGIC) {
if (fpAllocLog != NULL) {
fprintf(fpAllocLog, "%s:%d: memory not allocated by 'taos_malloc'.\n", file, line);
}
free(ptr);
return;
}
remove_mem_block(blk);
free(blk);
}
static void* malloc_detect_leak(size_t size, const char* file, uint32_t line) {
if (size == 0) { if (size == 0) {
return NULL; return NULL;
} }
...@@ -137,46 +157,46 @@ void* taos_malloc(size_t size, const char* file, uint32_t line) { ...@@ -137,46 +157,46 @@ void* taos_malloc(size_t size, const char* file, uint32_t line) {
return NULL; return NULL;
} }
if (line > UINT16_MAX && fpMemLeak != NULL) { if (line > UINT16_MAX && fpAllocLog != NULL) {
fprintf(fpMemLeak, "%s:%d: line number too large.\n", file, line); fprintf(fpAllocLog, "%s:%d: line number too large.\n", file, line);
} }
if (size > UINT32_MAX && fpMemLeak != NULL) { if (size > UINT32_MAX && fpAllocLog != NULL) {
fprintf(fpMemLeak, "%s:%d: size too large: %lld.\n", file, line, size); fprintf(fpAllocLog, "%s:%d: size too large: %zu.\n", file, line, size);
} }
blk->file = file; blk->file = file;
blk->line = (uint16_t)line; blk->line = (uint16_t)line;
blk->magic = MAGIC; blk->magic = MEMBLK_MAGIC;
blk->size = size; blk->size = size;
add_mem_block(blk); add_mem_block(blk);
return blk->data; return blk->data;
} }
void* taos_calloc(size_t num, size_t size, const char* file, uint32_t line) { static void* calloc_detect_leak(size_t num, size_t size, const char* file, uint32_t line) {
size *= num; size *= num;
void* p = taos_malloc(size, file, line); void* p = malloc_detect_leak(size, file, line);
if (p != NULL) { if (p != NULL) {
memset(p, 0, size); memset(p, 0, size);
} }
return p; return p;
} }
void* taos_realloc(void* ptr, size_t size, const char* file, uint32_t line) { static void* realloc_detect_leak(void* ptr, size_t size, const char* file, uint32_t line) {
if (size == 0) { if (size == 0) {
taos_free(ptr, file, line); free_detect_leak(ptr, file, line);
return NULL; return NULL;
} }
if (ptr == NULL) { if (ptr == NULL) {
return taos_malloc(size, file, line); return malloc_detect_leak(size, file, line);
} }
SMemBlock* blk = ((char*)ptr) - sizeof(SMemBlock); SMemBlock* blk = ((char*)ptr) - sizeof(SMemBlock);
if (blk->magic != MAGIC) { if (blk->magic != MEMBLK_MAGIC) {
if (fpMemLeak != NULL) { if (fpAllocLog != NULL) {
fprintf(fpMemLeak, "%s:%d: memory not allocated by 'taos_malloc'.\n", file, line); fprintf(fpAllocLog, "%s:%d: memory not allocated by 'taos_malloc'.\n", file, line);
} }
return realloc(ptr, size); return realloc(ptr, size);
} }
...@@ -189,8 +209,8 @@ void* taos_realloc(void* ptr, size_t size, const char* file, uint32_t line) { ...@@ -189,8 +209,8 @@ void* taos_realloc(void* ptr, size_t size, const char* file, uint32_t line) {
return NULL; return NULL;
} }
if (size > UINT32_MAX && fpMemLeak != NULL) { if (size > UINT32_MAX && fpAllocLog != NULL) {
fprintf(fpMemLeak, "%s:%d: size too large: %lld.\n", file, line, size); fprintf(fpAllocLog, "%s:%d: size too large: %zu.\n", file, line, size);
} }
blk = (SMemBlock*)p; blk = (SMemBlock*)p;
...@@ -199,27 +219,9 @@ void* taos_realloc(void* ptr, size_t size, const char* file, uint32_t line) { ...@@ -199,27 +219,9 @@ void* taos_realloc(void* ptr, size_t size, const char* file, uint32_t line) {
return blk->data; return blk->data;
} }
void taos_free(void* ptr, const char* file, uint32_t line) { static char* strdup_detect_leak(const char* str, const char* file, uint32_t line) {
if (ptr == NULL) {
return;
}
SMemBlock* blk = ((char*)ptr) - sizeof(SMemBlock);
if (blk->magic != MAGIC) {
if (fpMemLeak != NULL) {
fprintf(fpMemLeak, "%s:%d: memory not allocated by 'taos_malloc'.\n", file, line);
}
free(ptr);
return;
}
remove_mem_block(blk);
free(blk);
}
char* taos_strdup(const char* str, const char* file, uint32_t line) {
size_t len = strlen(str); size_t len = strlen(str);
char *p = taos_malloc(len + 1, file, line); char *p = malloc_detect_leak(len + 1, file, line);
if (p != NULL) { if (p != NULL) {
memcpy(p, str, len); memcpy(p, str, len);
p[len] = 0; p[len] = 0;
...@@ -227,12 +229,12 @@ char* taos_strdup(const char* str, const char* file, uint32_t line) { ...@@ -227,12 +229,12 @@ char* taos_strdup(const char* str, const char* file, uint32_t line) {
return p; return p;
} }
char* taos_strndup(const char* str, size_t size, const char* file, uint32_t line) { static char* strndup_detect_leak(const char* str, size_t size, const char* file, uint32_t line) {
size_t len = strlen(str); size_t len = strlen(str);
if (len > size) { if (len > size) {
len = size; len = size;
} }
char *p = taos_malloc(len + 1, file, line); char *p = malloc_detect_leak(len + 1, file, line);
if (p != NULL) { if (p != NULL) {
memcpy(p, str, len); memcpy(p, str, len);
p[len] = 0; p[len] = 0;
...@@ -240,13 +242,13 @@ char* taos_strndup(const char* str, size_t size, const char* file, uint32_t line ...@@ -240,13 +242,13 @@ char* taos_strndup(const char* str, size_t size, const char* file, uint32_t line
return p; return p;
} }
ssize_t taos_getline(char **lineptr, size_t *n, FILE *stream, const char* file, uint32_t line) { static ssize_t getline_detect_leak(char **lineptr, size_t *n, FILE *stream, const char* file, uint32_t line) {
char* buf = NULL; char* buf = NULL;
size_t bufSize = 0; size_t bufSize = 0;
ssize_t size = getline(&buf, &bufSize, stream); ssize_t size = getline(&buf, &bufSize, stream);
if (size != -1) { if (size != -1) {
if (*n < size + 1) { if (*n < size + 1) {
void* p = taos_realloc(*lineptr, size + 1, file, line); void* p = realloc_detect_leak(*lineptr, size + 1, file, line);
if (p == NULL) { if (p == NULL) {
free(buf); free(buf);
return -1; return -1;
...@@ -261,16 +263,16 @@ ssize_t taos_getline(char **lineptr, size_t *n, FILE *stream, const char* file, ...@@ -261,16 +263,16 @@ ssize_t taos_getline(char **lineptr, size_t *n, FILE *stream, const char* file,
return size; return size;
} }
void taos_dump_memory_leak() { static void dump_memory_leak() {
const char* hex = "0123456789ABCDEF"; const char* hex = "0123456789ABCDEF";
const char* fmt = ":%d: addr=0x%p, size=%d, content(first 16 bytes)='"; const char* fmt = ":%d: addr=0x%p, size=%d, content(first 16 bytes)=";
size_t numOfBlk = 0, totalSize = 0; size_t numOfBlk = 0, totalSize = 0;
if (fpMemLeak == NULL) { if (fpAllocLog == NULL) {
return; return;
} }
fputs("memory blocks allocated but not freed before exit:\n\n", fpMemLeak); fputs("memory blocks allocated but not freed before exit:\n", fpAllocLog);
while (atomic_val_compare_exchange_ptr(&lock, 0, 1) != 0); while (atomic_val_compare_exchange_ptr(&lock, 0, 1) != 0);
...@@ -278,74 +280,198 @@ void taos_dump_memory_leak() { ...@@ -278,74 +280,198 @@ void taos_dump_memory_leak() {
++numOfBlk; ++numOfBlk;
totalSize += blk->size; totalSize += blk->size;
fputs(blk->file, fpMemLeak); fputs(blk->file, fpAllocLog);
fprintf(fpMemLeak, fmt, blk->line, blk->data, blk->size); fprintf(fpAllocLog, fmt, blk->line, blk->data, blk->size);
uint8_t c = (uint8_t)(blk->data[0]);
fputc(hex[c >> 4], fpMemLeak);
fputc(hex[c & 0x0f], fpMemLeak);
char sep = '\'';
size_t size = blk->size > 16 ? 16 : blk->size; size_t size = blk->size > 16 ? 16 : blk->size;
for (size_t i = 1; i < size; ++i) { for (size_t i = 0; i < size; ++i) {
c = (uint8_t)(blk->data[i]); uint8_t c = (uint8_t)(blk->data[i]);
fputc(' ', fpMemLeak); fputc(sep, fpAllocLog);
fputc(hex[c >> 4], fpMemLeak); sep = ' ';
fputc(hex[c & 0x0f], fpMemLeak); fputc(hex[c >> 4], fpAllocLog);
fputc(hex[c & 0x0f], fpAllocLog);
} }
fputs("'\n", fpMemLeak); fputs("'\n", fpAllocLog);
} }
atomic_store_ptr(&lock, 0); atomic_store_ptr(&lock, 0);
fprintf("\nnumber of blocks: %lld, total bytes: %lld\n", numOfBlk, totalSize); fprintf(fpAllocLog, "\nnumber of blocks: %zu, total bytes: %zu\n", numOfBlk, totalSize);
if (fpMemLeak != stdout) { fflush(fpAllocLog);
fclose(fpMemLeak);
fpMemLeak = NULL;
}
} }
static void dump_memory_leak_at_sig(int sig) { static void dump_memory_leak_on_sig(int sig) {
fprintf(fpMemLeak, "signal %d received, exiting...\n", sig); fprintf(fpAllocLog, "signal %d received.\n", sig);
// restore default signal handler
struct sigaction act = {0}; struct sigaction act = {0};
act.sa_handler = SIG_DFL; act.sa_handler = SIG_DFL;
sigaction(sig, &act, NULL); sigaction(sig, &act, NULL);
taos_dump_memory_leak(); dump_memory_leak();
}
////////////////////////////////////////////////////////////////////////////////
// interface functions
void* taos_malloc(size_t size, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return malloc(size);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return malloc_random(size, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return malloc_detect_leak(size, file, line);
}
return malloc(size);
}
void* taos_calloc(size_t num, size_t size, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return calloc(num, size);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return calloc_random(num, size, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return calloc_detect_leak(num, size, file, line);
}
return calloc(num, size);
}
void* taos_realloc(void* ptr, size_t size, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return realloc(ptr, size);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return realloc_random(ptr, size, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return realloc_detect_leak(ptr, size, file, line);
}
return realloc(ptr, size);
} }
void taos_detect_memory_leak(const char* path, bool autoDump) { void taos_free(void* ptr, const char* file, uint32_t line) {
if (fpMemLeak != NULL) { switch (allocMode) {
printf("memory leak detection already enabled.\n"); case TAOS_ALLOC_MODE_DEFAULT:
return free(ptr);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return free(ptr);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return free_detect_leak(ptr, file, line);
}
return free(ptr);
}
char* taos_strdup(const char* str, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return strdup(str);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return strdup_random(str, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return strdup_detect_leak(str, file, line);
}
return strdup(str);
}
char* taos_strndup(const char* str, size_t size, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return strndup(str, size);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return strndup_random(str, size, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return strndup_detect_leak(str, size, file, line);
}
return strndup(str, size);
}
ssize_t taos_getline(char **lineptr, size_t *n, FILE *stream, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return getline(lineptr, n, stream);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return getline_random(lineptr, n, stream, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return getline_detect_leak(lineptr, n, stream, file, line);
}
return getline(lineptr, n, stream);
}
static void close_alloc_log() {
if (fpAllocLog != NULL) {
if (fpAllocLog != stdout) {
fclose(fpAllocLog);
}
fpAllocLog = NULL;
}
}
void taosSetAllocMode(int mode, const char* path, bool autoDump) {
assert(mode >= TAOS_ALLOC_MODE_DEFAULT);
assert(mode <= TAOS_ALLOC_MODE_DETECT_LEAK);
if (fpAllocLog != NULL || allocMode != TAOS_ALLOC_MODE_DEFAULT) {
printf("memory allocation mode can only be set once.\n");
return; return;
} }
if (path == NULL || path[0] == 0) { if (path == NULL || path[0] == 0) {
fpMemLeak = stdout; fpAllocLog = stdout;
} else if ((fpMemLeak = fopen(path, "w")) == NULL) { } else if ((fpAllocLog = fopen(path, "w")) != NULL) {
printf("failed to open memory leak dump file '%s', errno=%d\n", path, errno); atexit(close_alloc_log);
} else {
printf("failed to open memory allocation log file '%s', errno=%d\n", path, errno);
return;
}
allocMode = mode;
if (mode == TAOS_ALLOC_MODE_RANDOM_FAIL) {
startTime = taosGetTimestampSec() + 10;
return; return;
} }
if (autoDump) { if (autoDump && mode == TAOS_ALLOC_MODE_DETECT_LEAK) {
atexit(taos_dump_memory_leak); atexit(dump_memory_leak);
struct sigaction act = {0}; struct sigaction act = {0};
act.sa_handler = dump_memory_leak_at_sig; act.sa_handler = dump_memory_leak_on_sig;
sigaction(SIGFPE, &act, NULL); sigaction(SIGFPE, &act, NULL);
sigaction(SIGSEGV, &act, NULL); sigaction(SIGSEGV, &act, NULL);
sigaction(SIGILL, &act, NULL); sigaction(SIGILL, &act, NULL);
} }
} }
#endif void taosDumpMemoryLeak() {
dump_memory_leak();
close_alloc_log();
}
#if TAOS_MEM_CHECK != 2 #else // 'TAOS_MEM_CHECK' not defined
void taos_dump_memory_leak() {
void taosSetAllocMode(int mode, const char* path, bool autoDump) {
// do nothing // do nothing
} }
void taos_detect_memory_leak(const char* path, bool autoDump) { void taosDumpMemoryLeak() {
printf("memory leak detection not enabled, please set 'TAOS_MEM_CHECK' to 2."); // do nothing
} }
#endif
\ No newline at end of file #endif // TAOS_MEM_CHECK
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册