是否必须检查什么回报的问题malloc
是有争议的,并且总是引起激烈的讨论。
有人认为我们应该尝试处理各种运行时错误,包括。和OOM情况。其他人则认为,OOM几乎无能为力,最好让应用程序崩溃。在第二个人的一边,还有一个事实,即附加的OOM处理逻辑很难测试。而且,如果代码未经测试,则几乎肯定无法正常工作。
我完全同意,您不应实施不打算测试的错误处理逻辑。它几乎肯定不会改善任何东西,甚至更糟-破坏一切。
是否尝试在库/应用程序中处理OOM的情况存在争议,我们在这里不再赘述。作为本出版物的一部分,我只想分享我的经验,即如何测试用C / C ++编写的应用程序中处理OOM情况的已实现逻辑。讨论将围绕Linux和macOS操作系统进行。由于多种原因,将绕过Windows。
介绍
我们都希望OOM永远不会发生,但是在现实生活中,由于以下原因,这并非总是可能的:
- RAM总是有限的。
- 不总是启用SWAP。
- 应用程序的行为并不总是令人满意,有时会尝试分配不切实际的大量内存,从而干扰自己和其他人。
- 32位应用程序仍然存在。
- 过量提交并非始终启用。
ulimit
例如,可以限制内存消耗。-
LD_PRELOAD
.
, , , OOM . , , :
- , - .
- OOM . .
- . , .
, , SQLite. , . . SQLite .
, , , . OOM Killer, , . , C++, .
1.
, OOM . my_malloc
my_free
malloc
free
.
my_free
. my_realloc
.
my_malloc
malloc
. my_malloc
, NULL
.
, :
- 3rd party .
-
malloc
. -strdup
. -
malloc
’ , , . - C++
malloc
free
.
- .
2.
Linux LD_PRELOAD
. . malloc
. , malloc
/realloc
/free
(weak
). , macOS LD_PRELOAD
, DYLD_INSERT_LIBRARIES
.
, , LD_PRELOAD
DYLD_INSERT_LIBRARIES
malloc
/realloc
NULL
.
, "" . , .
, "" , , . :
-
main
. , . - Runtime macOS " ". , , , .
-
printf
macOSSIGSEGV
/SIGBUS
. - ,
std::bad_alloc
, . , , , OOM.std::terminate
. . -
std::thread
std::terminate
macOS.
UPDATE: Travis CI , macOS / Xcode , std::bad_alloc
, std::thread
std::terminate
.
Overthrower. - malloc
NULL
. Overthrower - , .
3.
main
, main
, main
runtime . main
, , .. - main
.
, main
. Overthrower, OOM . Overthrower , .
:
activateOverthrower
deactivateOverthrower
:
#ifdef __cplusplus
extern "C" {
#endif
void activateOverthrower() __attribute__((weak));
unsigned int deactivateOverthrower() __attribute__((weak));
#ifdef __cplusplus
}
#endif
Overthrower LD_PRELOAD
, NULL
, , .
, , :
int main(int argc, char** argv)
{
activateOverthrower();
// Some code we want to test ...
deactivateOverthrower();
}
activateOverthrower
/deactivateOverthrower
, :
TEST(Foo, Bar)
{
activateOverthrower();
// Some code we want to test ...
deactivateOverthrower();
}
, -, , Overthrower , :
#ifdef __cplusplus
extern "C" {
#endif
void pauseOverthrower(unsigned int duration) __attribute__((weak));
void resumeOverthrower() __attribute__((weak));
#ifdef __cplusplus
}
#endif
:
TEST(Foo, Bar)
{
activateOverthrower();
// Some code we want to test ...
pauseOverthrower(0);
// Some fragile code we can not fix ...
resumeOverthrower();
// Some code we want to test ...
deactivateOverthrower();
}
__cxa_allocate_exception
, , , malloc
, NULL
. , Linux, malloc
, __cxa_allocate_exception
(emergency buffer), , . .
macOS , , , , std::bad_alloc
, std::terminate
.
UPDATE: , macOS / Xcode .
, , , __cxa_allocate_exception
malloc
. - Overthrower’ malloc
. Overthrower malloc
__cxa_allocate_exception
.
, , , macOS __cxa_atexit
, Linux dlerror
. .
Overthrower , malloc
free
. Overthrower’ , activateOverthrower
deactivateOverthrower
, :
overthrower got deactivation signal.
overthrower will not fail allocations anymore.
overthrower has detected not freed memory blocks with following addresses:
0x0000000000dd1e70 - 2 - 128
0x0000000000dd1de0 - 1 - 128
0x0000000000dd1030 - 0 - 128
^^^^^^^^^^^^^^^^^^ | ^^^^^^ | ^^^^^^^^^^
pointer | malloc | block size
|invocation|
| number |
Overthrower , , .
Overthrower’, , valgrind. , OOM. , , Overthrower . Overthrower , , deactivateOverthrower
, stderr
.
Overthrower 3 :
- Random —
rand() % duty_cycle == 0
.duty_cycle
, . - Step — (
malloc_seq_num >= delay
),delay
.
<--- delay --->
--------------+
|
| All further allocations fail
|
+------------------------------
- Pulse — (
malloc_seq_num > delay && malloc_seq_num <= delay + duration
),delay
duration
.
<--- delay --->
--------------+ +------------------------------
| |
| | All further allocations pass
| |
+----------------+
<--- duration --->
:
OVERTHROWER_STRATEGY
OVERTHROWER_SEED
OVERTHROWER_DUTY_CYCLE
OVERTHROWER_DELAY
OVERTHROWER_DURATION
activateOverthrower
. , Overthrower , /dev/urandom
.
- Overthrower
malloc
/. - .
- Overthrower .
- Overthrower .
- Overthrower , .
- Overthrower’ .
- Overthrower Overthrower-aware . , .
- Overthrower本身已在Ubuntu(自14.04起)和macOS(自Sierra(10.12)和Xcode 8.3起)上进行了测试。在测试过程中,Overthrower尝试掉线。
- 如果系统中出现真正的OOM,则Overthrower会竭尽所能不摔倒。