ljmp 和 setjmp 之间的内存泄漏
memory leak between ljmp and setjmp
我有问题。我正在从事一个预期存在分段错误的项目,我必须使用 setjmp 和 ljmp 机制捕获分段错误并更改默认行为(即应用程序崩溃)。当代码抛出分段错误时,内存分配已经完成。有什么办法可以解除调用 setjmp 后完成的内存分配吗?
简单的话:我想解除对 setjmp 的初始调用和从 ljmp 调用的内存分配之间的分配。这是一个小而有效的代码,我们可以讨论...
谢谢
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
static jmp_buf buf;
static void
addSignalToMask()
{
sigset_t sigset;
if ( 0 > sigprocmask(0,NULL,&sigset)){
fprintf(stderr," error while retreiving procmask \n");
exit(1);
}
if ( -1 == sigaddset(&sigset,SIGSEGV) ){
/* on error errno is set */
perror(" SIGSEGV cannot be added to signal set \n ");
exit(1);
}
if ( 0 > sigprocmask(SIG_UNBLOCK,&sigset,NULL)){
fprintf(stderr," error while retreiving procmask \n");
exit(1);
}
fprintf(stdout, " SIG_SEGV added to signal set \n");
return;
}
static void
signalHandler(int arg)
{
fprintf(stdout ," I am in signal handler \n");
longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
}
static void
throwSegmentation()
{
int * ptr = 0x0;
/* a leak of 10x4 = 40 bytes */
void * leak = malloc(sizeof(int) * 10);
/* now attempting to write on address 0x0 */
*ptr = 0xdeadbeef;
}
static void
setUpAndThrowSeg()
{
if ( 0 == setjmp(buf) ) {
fprintf(stdout," jump set \n");
throwSegmentation();
}else {
/* remove blocked SIGSEGV from procmask */
fprintf(stdout," returned from segmentation\n");
addSignalToMask();
}
}
int main() {
int count = 10;
if (SIG_ERR == signal(SIGSEGV, signalHandler)){
fprintf(stderr," signal handler not set up \n");
exit(1);
}
while ( 0 != count --) {
fprintf(stdout, " throwing again \n");
setUpAndThrowSeg();
}
return 0;
}
实际上没有办法用股票 malloc
做到这一点。没有便携式工具可以让您跟踪自某个时间点以来已完成的分配。
你可以做的是这样的:创建一个包装 malloc
的函数,并将每个新分配的内存区域添加到一个链表中。当您需要清除内存泄漏时,遍历此列表和 free
您在那里找到的所有块。当然,这只有在您可以保证没有指针指向已分配区域的情况下才有效。
重新设计您的控制流可能是个好主意,这样在您想要中止控制期间不会发生内存分配。
我有问题。我正在从事一个预期存在分段错误的项目,我必须使用 setjmp 和 ljmp 机制捕获分段错误并更改默认行为(即应用程序崩溃)。当代码抛出分段错误时,内存分配已经完成。有什么办法可以解除调用 setjmp 后完成的内存分配吗? 简单的话:我想解除对 setjmp 的初始调用和从 ljmp 调用的内存分配之间的分配。这是一个小而有效的代码,我们可以讨论...
谢谢
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
static jmp_buf buf;
static void
addSignalToMask()
{
sigset_t sigset;
if ( 0 > sigprocmask(0,NULL,&sigset)){
fprintf(stderr," error while retreiving procmask \n");
exit(1);
}
if ( -1 == sigaddset(&sigset,SIGSEGV) ){
/* on error errno is set */
perror(" SIGSEGV cannot be added to signal set \n ");
exit(1);
}
if ( 0 > sigprocmask(SIG_UNBLOCK,&sigset,NULL)){
fprintf(stderr," error while retreiving procmask \n");
exit(1);
}
fprintf(stdout, " SIG_SEGV added to signal set \n");
return;
}
static void
signalHandler(int arg)
{
fprintf(stdout ," I am in signal handler \n");
longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
}
static void
throwSegmentation()
{
int * ptr = 0x0;
/* a leak of 10x4 = 40 bytes */
void * leak = malloc(sizeof(int) * 10);
/* now attempting to write on address 0x0 */
*ptr = 0xdeadbeef;
}
static void
setUpAndThrowSeg()
{
if ( 0 == setjmp(buf) ) {
fprintf(stdout," jump set \n");
throwSegmentation();
}else {
/* remove blocked SIGSEGV from procmask */
fprintf(stdout," returned from segmentation\n");
addSignalToMask();
}
}
int main() {
int count = 10;
if (SIG_ERR == signal(SIGSEGV, signalHandler)){
fprintf(stderr," signal handler not set up \n");
exit(1);
}
while ( 0 != count --) {
fprintf(stdout, " throwing again \n");
setUpAndThrowSeg();
}
return 0;
}
实际上没有办法用股票 malloc
做到这一点。没有便携式工具可以让您跟踪自某个时间点以来已完成的分配。
你可以做的是这样的:创建一个包装 malloc
的函数,并将每个新分配的内存区域添加到一个链表中。当您需要清除内存泄漏时,遍历此列表和 free
您在那里找到的所有块。当然,这只有在您可以保证没有指针指向已分配区域的情况下才有效。
重新设计您的控制流可能是个好主意,这样在您想要中止控制期间不会发生内存分配。