Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
279ac970
TDengine
项目概览
taosdata
/
TDengine
1 年多 前同步成功
通知
1185
Star
22016
Fork
4786
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
279ac970
编写于
11月 27, 2019
作者:
S
slguan
提交者:
GitHub
11月 27, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #785 from taosdata/feature/detect-mem-leak
Feature/detect mem leak
上级
574f9d4c
91f5600c
变更
8
显示空白变更内容
内联
并排
Showing
8 changed file
with
536 addition
and
49 deletion
+536
-49
CMakeLists.txt
CMakeLists.txt
+3
-1
src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
+16
-0
src/client/src/TSDBJNIConnector.c
src/client/src/TSDBJNIConnector.c
+14
-0
src/connector/go/src/taosSql/utils.go
src/connector/go/src/taosSql/utils.go
+23
-1
src/inc/tutil.h
src/inc/tutil.h
+29
-12
src/os/linux/src/tsystem.c
src/os/linux/src/tsystem.c
+4
-1
src/system/detail/src/dnodeService.c
src/system/detail/src/dnodeService.c
+14
-0
src/util/src/tmem.c
src/util/src/tmem.c
+433
-34
未找到文件。
CMakeLists.txt
浏览文件 @
279ac970
...
...
@@ -125,7 +125,9 @@ IF (NOT DEFINED TD_CLUSTER)
# debug flag
#
# ADD_DEFINITIONS(-D_CHECK_HEADER_FILE_)
# ADD_DEFINITIONS(-D_TAOS_MEM_TEST_)
IF
(
${
MEM_CHECK
}
MATCHES
"true"
)
ADD_DEFINITIONS
(
-DTAOS_MEM_CHECK
)
ENDIF
()
IF
(
TD_CLUSTER
)
ADD_DEFINITIONS
(
-DCLUSTER
)
...
...
src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
浏览文件 @
279ac970
...
...
@@ -9,6 +9,22 @@ extern "C" {
#endif
#undef com_taosdata_jdbc_TSDBJNIConnector_INVALID_CONNECTION_POINTER_VALUE
#define com_taosdata_jdbc_TSDBJNIConnector_INVALID_CONNECTION_POINTER_VALUE 0LL
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method:
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT
void
JNICALL
Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp
(
JNIEnv
*
,
jclass
,
jint
,
jstring
,
jboolean
);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method:
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT
void
JNICALL
Java_com_taosdata_jdbc_TSDBJNIConnector_dumpMemoryLeakImp
(
JNIEnv
*
,
jclass
);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: initImp
...
...
src/client/src/TSDBJNIConnector.c
浏览文件 @
279ac970
...
...
@@ -111,6 +111,20 @@ void jniGetGlobalMethod(JNIEnv *env) {
jniTrace
(
"native method register finished"
);
}
JNIEXPORT
void
JNICALL
Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp
(
JNIEnv
*
env
,
jobject
jobj
,
jint
jMode
,
jstring
jPath
,
jboolean
jAutoDump
)
{
if
(
jPath
!=
NULL
)
{
const
char
*
path
=
(
*
env
)
->
GetStringUTFChars
(
env
,
jPath
,
NULL
);
taosSetAllocMode
(
jMode
,
path
,
!!
jAutoDump
);
(
*
env
)
->
ReleaseStringUTFChars
(
env
,
jPath
,
path
);
}
else
{
taosSetAllocMode
(
jMode
,
NULL
,
!!
jAutoDump
);
}
}
JNIEXPORT
void
JNICALL
Java_com_taosdata_jdbc_TSDBJNIConnector_dumpMemoryLeakImp
(
JNIEnv
*
env
,
jobject
jobj
)
{
taosDumpMemoryLeak
();
}
JNIEXPORT
void
JNICALL
Java_com_taosdata_jdbc_TSDBJNIConnector_initImp
(
JNIEnv
*
env
,
jobject
jobj
,
jstring
jconfigDir
)
{
if
(
jconfigDir
!=
NULL
)
{
const
char
*
confDir
=
(
*
env
)
->
GetStringUTFChars
(
env
,
jconfigDir
,
NULL
);
...
...
src/connector/go/src/taosSql/utils.go
浏览文件 @
279ac970
...
...
@@ -12,15 +12,25 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package
taosSql
/*
#cgo CFLAGS : -I/usr/include
#include <stdlib.h>
#cgo LDFLAGS: -L/usr/lib -ltaos
void taosSetAllocMode(int mode, const char* path, _Bool autoDump);
void taosDumpMemoryLeak();
*/
import
"C"
import
(
"database/sql/driver"
"errors"
"fmt"
"sync/atomic"
"time"
"unsafe"
)
// Returns the bool value of the input.
...
...
@@ -398,3 +408,15 @@ func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
}
/******************************************************************************
* Utils for C memory issues debugging *
******************************************************************************/
func
SetAllocMode
(
mode
int32
,
path
string
)
{
cpath
:=
C
.
CString
(
path
)
defer
C
.
free
(
unsafe
.
Pointer
(
cpath
))
C
.
taosSetAllocMode
(
C
.
int
(
mode
),
cpath
,
false
)
}
func
DumpMemoryLeak
()
{
C
.
taosDumpMemoryLeak
()
}
src/inc/tutil.h
浏览文件 @
279ac970
...
...
@@ -187,18 +187,35 @@ static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, unsigned int inLen, cha
char
*
taosIpStr
(
uint32_t
ipInt
);
#ifdef _TAOS_MEM_TEST_
// Use during test to simulate the success and failure scenarios of memory allocation
extern
void
*
taos_malloc
(
unsigned
int
size
,
char
*
_func
);
extern
void
*
taos_calloc
(
unsigned
int
num
,
unsigned
int
size
,
char
*
_func
);
extern
void
*
taos_realloc
(
void
*
ptr
,
unsigned
int
size
,
char
*
_func
);
extern
void
taos_free
(
void
*
ptr
);
#define malloc(size) taos_malloc(size, __FUNCTION__)
#define calloc(num, size) taos_calloc(num, size, __FUNCTION__)
#define realloc(ptr, size) taos_realloc(ptr, size, __FUNCTION__)
#define free(ptr) taos_free(ptr)
#endif
#define TAOS_ALLOC_MODE_DEFAULT 0
#define TAOS_ALLOC_MODE_RANDOM_FAIL 1
#define TAOS_ALLOC_MODE_DETECT_LEAK 2
void
taosSetAllocMode
(
int
mode
,
const
char
*
path
,
bool
autoDump
);
void
taosDumpMemoryLeak
();
#ifdef TAOS_MEM_CHECK
void
*
taos_malloc
(
size_t
size
,
const
char
*
file
,
uint32_t
line
);
void
*
taos_calloc
(
size_t
num
,
size_t
size
,
const
char
*
file
,
uint32_t
line
);
void
*
taos_realloc
(
void
*
ptr
,
size_t
size
,
const
char
*
file
,
uint32_t
line
);
void
taos_free
(
void
*
ptr
,
const
char
*
file
,
uint32_t
line
);
char
*
taos_strdup
(
const
char
*
str
,
const
char
*
file
,
uint32_t
line
);
char
*
taos_strndup
(
const
char
*
str
,
size_t
size
,
const
char
*
file
,
uint32_t
line
);
ssize_t
taos_getline
(
char
**
lineptr
,
size_t
*
n
,
FILE
*
stream
,
const
char
*
file
,
uint32_t
line
);
#ifndef TAOS_MEM_CHECK_IMPL
#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__)
#endif // TAOS_MEM_CHECK_IMPL
#endif // TAOS_MEM_CHECK
#ifdef __cplusplus
}
...
...
src/os/linux/src/tsystem.c
浏览文件 @
279ac970
...
...
@@ -81,6 +81,7 @@ bool taosGetProcMemory(float *memoryUsedMB) {
char
*
line
=
NULL
;
while
(
!
feof
(
fp
))
{
tfree
(
line
);
len
=
0
;
getline
(
&
line
,
&
len
,
fp
);
if
(
line
==
NULL
)
{
break
;
...
...
@@ -137,7 +138,7 @@ bool taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) {
return
false
;
}
size_t
len
;
size_t
len
=
0
;
char
*
line
=
NULL
;
getline
(
&
line
,
&
len
,
fp
);
if
(
line
==
NULL
)
{
...
...
@@ -409,6 +410,7 @@ bool taosGetCardInfo(int64_t *bytes) {
while
(
!
feof
(
fp
))
{
tfree
(
line
);
len
=
0
;
getline
(
&
line
,
&
len
,
fp
);
if
(
line
==
NULL
)
{
break
;
...
...
@@ -480,6 +482,7 @@ bool taosReadProcIO(int64_t *readbyte, int64_t *writebyte) {
while
(
!
feof
(
fp
))
{
tfree
(
line
);
len
=
0
;
getline
(
&
line
,
&
len
,
fp
);
if
(
line
==
NULL
)
{
break
;
...
...
src/system/detail/src/dnodeService.c
浏览文件 @
279ac970
...
...
@@ -61,6 +61,20 @@ int main(int argc, char *argv[]) {
return
0
;
}
else
if
(
strcmp
(
argv
[
i
],
"-k"
)
==
0
)
{
dnodeParseParameterK
();
#ifdef TAOS_MEM_CHECK
}
else
if
(
strcmp
(
argv
[
i
],
"--alloc-random-fail"
)
==
0
)
{
if
((
i
<
argc
-
1
)
&&
(
argv
[
i
+
1
][
0
]
!=
'-'
))
{
taosSetAllocMode
(
TAOS_ALLOC_MODE_RANDOM_FAIL
,
argv
[
++
i
],
true
);
}
else
{
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
}
}
...
...
src/util/src/tmem.c
浏览文件 @
279ac970
...
...
@@ -16,63 +16,462 @@
#include "os.h"
#include "tlog.h"
#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
();
static
int32_t
startTime
=
0
;
static
int64_t
m_curLimit
=
100
*
1024
;
static
int32_t
startTime
=
INT32_MAX
;;
bool
isMallocMem
(
unsigned
int
size
,
char
*
_func
)
{
if
(
0
==
startTime
)
{
startTime
=
taosGetTimestampSec
()
;
return
true
;
}
else
{
int32_t
currentTime
=
taosGetTimestampSec
();
if
(
currentTime
-
startTime
<
10
)
return
tru
e
;
static
bool
random_alloc_fail
(
size_t
size
,
const
char
*
file
,
uint32_t
line
)
{
if
(
taosGetTimestampSec
()
<
startTime
)
{
return
false
;
}
if
(
size
<
100
*
(
size_t
)
1024
)
{
return
fals
e
;
}
if
(
size
>
m_curLimit
)
{
if
(
3
==
rand
()
%
20
)
{
pTrace
(
"====no alloc mem in func: %s, size:%d"
,
_func
,
size
);
if
(
rand
()
%
20
!=
0
)
{
return
false
;
}
if
(
fpAllocLog
!=
NULL
)
{
fprintf
(
fpAllocLog
,
"%s:%d: memory allocation of %zu bytes will fail.
\n
"
,
file
,
line
,
size
);
}
return
true
;
}
void
*
taos_malloc
(
unsigned
int
size
,
char
*
_func
)
{
static
void
*
malloc_random
(
size_t
size
,
const
char
*
file
,
uint32_t
line
)
{
return
random_alloc_fail
(
size
,
file
,
line
)
?
NULL
:
malloc
(
size
);
}
if
(
false
==
isMallocMem
(
size
,
_func
))
{
return
NULL
;
static
void
*
calloc_random
(
size_t
num
,
size_t
size
,
const
char
*
file
,
uint32_t
line
)
{
return
random_alloc_fail
(
num
*
size
,
file
,
line
)
?
NULL
:
calloc
(
num
,
size
);
}
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
);
}
static
char
*
strdup_random
(
const
char
*
str
,
const
char
*
file
,
uint32_t
line
)
{
size_t
len
=
strlen
(
str
);
return
random_alloc_fail
(
len
+
1
,
file
,
line
)
?
NULL
:
strdup
(
str
);
}
static
char
*
strndup_random
(
const
char
*
str
,
size_t
size
,
const
char
*
file
,
uint32_t
line
)
{
size_t
len
=
strlen
(
str
);
if
(
len
>
size
)
{
len
=
size
;
}
return
random_alloc_fail
(
len
+
1
,
file
,
line
)
?
NULL
:
strndup
(
str
,
len
);
}
void
*
p
=
NULL
;
p
=
malloc
(
size
);
return
p
;
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
);
}
////////////////////////////////////////////////////////////////////////////////
// memory allocator with leak detection
#define MEMBLK_MAGIC 0x55AA
typedef
struct
SMemBlock
{
const
char
*
file
;
uint16_t
line
;
uint16_t
magic
;
uint32_t
size
;
struct
SMemBlock
*
prev
;
struct
SMemBlock
*
next
;
// TODO: need pading in 32bit platform
char
data
[
0
];
}
SMemBlock
;
static
SMemBlock
*
blocks
=
NULL
;
static
uintptr_t
lock
=
0
;
static
void
add_mem_block
(
SMemBlock
*
blk
)
{
blk
->
prev
=
NULL
;
while
(
atomic_val_compare_exchange_ptr
(
&
lock
,
0
,
1
)
!=
0
);
blk
->
next
=
blocks
;
if
(
blocks
!=
NULL
)
{
blocks
->
prev
=
blk
;
}
blocks
=
blk
;
atomic_store_ptr
(
&
lock
,
0
);
}
static
void
remove_mem_block
(
SMemBlock
*
blk
)
{
while
(
atomic_val_compare_exchange_ptr
(
&
lock
,
0
,
1
)
!=
0
);
if
(
blocks
==
blk
)
{
blocks
=
blk
->
next
;
}
if
(
blk
->
prev
!=
NULL
)
{
blk
->
prev
->
next
=
blk
->
next
;
}
if
(
blk
->
next
!=
NULL
)
{
blk
->
next
->
prev
=
blk
->
prev
;
}
atomic_store_ptr
(
&
lock
,
0
);
blk
->
prev
=
NULL
;
blk
->
next
=
NULL
;
}
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 is allocated by default allocator.
\n
"
,
file
,
line
);
}
free
(
ptr
);
return
;
}
remove_mem_block
(
blk
);
free
(
blk
);
}
void
*
taos_calloc
(
unsigned
int
num
,
unsigned
int
size
,
char
*
_func
)
{
static
void
*
malloc_detect_leak
(
size_t
size
,
const
char
*
file
,
uint32_t
line
)
{
if
(
size
==
0
)
{
return
NULL
;
}
if
(
false
==
isMallocMem
(
size
,
_func
))
{
SMemBlock
*
blk
=
(
SMemBlock
*
)
malloc
(
size
+
sizeof
(
SMemBlock
));
if
(
blk
==
NULL
)
{
return
NULL
;
}
void
*
p
=
NULL
;
p
=
calloc
(
num
,
size
);
if
(
line
>
UINT16_MAX
&&
fpAllocLog
!=
NULL
)
{
fprintf
(
fpAllocLog
,
"%s:%d: line number too large.
\n
"
,
file
,
line
);
}
if
(
size
>
UINT32_MAX
&&
fpAllocLog
!=
NULL
)
{
fprintf
(
fpAllocLog
,
"%s:%d: size too large: %zu.
\n
"
,
file
,
line
,
size
);
}
blk
->
file
=
file
;
blk
->
line
=
(
uint16_t
)
line
;
blk
->
magic
=
MEMBLK_MAGIC
;
blk
->
size
=
size
;
add_mem_block
(
blk
);
return
blk
->
data
;
}
static
void
*
calloc_detect_leak
(
size_t
num
,
size_t
size
,
const
char
*
file
,
uint32_t
line
)
{
size
*=
num
;
void
*
p
=
malloc_detect_leak
(
size
,
file
,
line
);
if
(
p
!=
NULL
)
{
memset
(
p
,
0
,
size
);
}
return
p
;
}
void
*
taos_realloc
(
void
*
ptr
,
unsigned
int
size
,
char
*
_func
)
{
static
void
*
realloc_detect_leak
(
void
*
ptr
,
size_t
size
,
const
char
*
file
,
uint32_t
line
)
{
if
(
size
==
0
)
{
free_detect_leak
(
ptr
,
file
,
line
);
return
NULL
;
}
if
(
ptr
==
NULL
)
{
return
malloc_detect_leak
(
size
,
file
,
line
);
}
if
(
false
==
isMallocMem
(
size
,
_func
))
{
SMemBlock
*
blk
=
((
char
*
)
ptr
)
-
sizeof
(
SMemBlock
);
if
(
blk
->
magic
!=
MEMBLK_MAGIC
)
{
if
(
fpAllocLog
!=
NULL
)
{
fprintf
(
fpAllocLog
,
"%s:%d: memory is allocated by default allocator.
\n
"
,
file
,
line
);
}
return
realloc
(
ptr
,
size
);
}
remove_mem_block
(
blk
);
void
*
p
=
realloc
(
blk
,
size
+
sizeof
(
SMemBlock
));
if
(
p
==
NULL
)
{
add_mem_block
(
blk
);
return
NULL
;
}
void
*
p
=
NULL
;
p
=
realloc
(
ptr
,
size
);
if
(
size
>
UINT32_MAX
&&
fpAllocLog
!=
NULL
)
{
fprintf
(
fpAllocLog
,
"%s:%d: size too large: %zu.
\n
"
,
file
,
line
,
size
);
}
blk
=
(
SMemBlock
*
)
p
;
blk
->
size
=
size
;
add_mem_block
(
blk
);
return
blk
->
data
;
}
static
char
*
strdup_detect_leak
(
const
char
*
str
,
const
char
*
file
,
uint32_t
line
)
{
size_t
len
=
strlen
(
str
);
char
*
p
=
malloc_detect_leak
(
len
+
1
,
file
,
line
);
if
(
p
!=
NULL
)
{
memcpy
(
p
,
str
,
len
);
p
[
len
]
=
0
;
}
return
p
;
}
void
taos_free
(
void
*
ptr
)
{
free
(
ptr
);
static
char
*
strndup_detect_leak
(
const
char
*
str
,
size_t
size
,
const
char
*
file
,
uint32_t
line
)
{
size_t
len
=
strlen
(
str
);
if
(
len
>
size
)
{
len
=
size
;
}
char
*
p
=
malloc_detect_leak
(
len
+
1
,
file
,
line
);
if
(
p
!=
NULL
)
{
memcpy
(
p
,
str
,
len
);
p
[
len
]
=
0
;
}
return
p
;
}
static
ssize_t
getline_detect_leak
(
char
**
lineptr
,
size_t
*
n
,
FILE
*
stream
,
const
char
*
file
,
uint32_t
line
)
{
char
*
buf
=
NULL
;
size_t
bufSize
=
0
;
ssize_t
size
=
getline
(
&
buf
,
&
bufSize
,
stream
);
if
(
size
!=
-
1
)
{
if
(
*
n
<
size
+
1
)
{
void
*
p
=
realloc_detect_leak
(
*
lineptr
,
size
+
1
,
file
,
line
);
if
(
p
==
NULL
)
{
free
(
buf
);
return
-
1
;
}
*
lineptr
=
(
char
*
)
p
;
*
n
=
size
+
1
;
}
memcpy
(
*
lineptr
,
buf
,
size
+
1
);
}
free
(
buf
);
return
size
;
}
static
void
dump_memory_leak
()
{
const
char
*
hex
=
"0123456789ABCDEF"
;
const
char
*
fmt
=
":%d: addr=%p, size=%d, content(first 16 bytes)="
;
size_t
numOfBlk
=
0
,
totalSize
=
0
;
if
(
fpAllocLog
==
NULL
)
{
return
;
}
fputs
(
"memory blocks allocated but not freed before exit:
\n
"
,
fpAllocLog
);
while
(
atomic_val_compare_exchange_ptr
(
&
lock
,
0
,
1
)
!=
0
);
for
(
SMemBlock
*
blk
=
blocks
;
blk
!=
NULL
;
blk
=
blk
->
next
)
{
++
numOfBlk
;
totalSize
+=
blk
->
size
;
fputs
(
blk
->
file
,
fpAllocLog
);
fprintf
(
fpAllocLog
,
fmt
,
blk
->
line
,
blk
->
data
,
blk
->
size
);
char
sep
=
'\''
;
size_t
size
=
blk
->
size
>
16
?
16
:
blk
->
size
;
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
{
uint8_t
c
=
(
uint8_t
)(
blk
->
data
[
i
]);
fputc
(
sep
,
fpAllocLog
);
sep
=
' '
;
fputc
(
hex
[
c
>>
4
],
fpAllocLog
);
fputc
(
hex
[
c
&
0x0f
],
fpAllocLog
);
}
fputs
(
"'
\n
"
,
fpAllocLog
);
}
atomic_store_ptr
(
&
lock
,
0
);
fprintf
(
fpAllocLog
,
"
\n
number of blocks: %zu, total bytes: %zu
\n
"
,
numOfBlk
,
totalSize
);
fflush
(
fpAllocLog
);
}
static
void
dump_memory_leak_on_sig
(
int
sig
)
{
fprintf
(
fpAllocLog
,
"signal %d received.
\n
"
,
sig
);
// restore default signal handler
struct
sigaction
act
=
{
0
};
act
.
sa_handler
=
SIG_DFL
;
sigaction
(
sig
,
&
act
,
NULL
);
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_free
(
void
*
ptr
,
const
char
*
file
,
uint32_t
line
)
{
switch
(
allocMode
)
{
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
;
}
if
(
path
==
NULL
||
path
[
0
]
==
0
)
{
fpAllocLog
=
stdout
;
}
else
if
((
fpAllocLog
=
fopen
(
path
,
"w"
))
!=
NULL
)
{
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
;
}
if
(
autoDump
&&
mode
==
TAOS_ALLOC_MODE_DETECT_LEAK
)
{
atexit
(
dump_memory_leak
);
struct
sigaction
act
=
{
0
};
act
.
sa_handler
=
dump_memory_leak_on_sig
;
sigaction
(
SIGFPE
,
&
act
,
NULL
);
sigaction
(
SIGSEGV
,
&
act
,
NULL
);
sigaction
(
SIGILL
,
&
act
,
NULL
);
}
}
void
taosDumpMemoryLeak
()
{
dump_memory_leak
();
close_alloc_log
();
}
#else // 'TAOS_MEM_CHECK' not defined
void
taosSetAllocMode
(
int
mode
,
const
char
*
path
,
bool
autoDump
)
{
// do nothing
}
void
taosDumpMemoryLeak
()
{
// do nothing
}
#endif // TAOS_MEM_CHECK
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录