【问题标题】:memory leak between ljmp and setjmpljmp 和 setjmp 之间的内存泄漏
【发布时间】:2015-02-26 10:23:23
【问题描述】:

我有问题。我正在处理一个预期存在分段错误的项目,我必须使用 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;
}

【问题讨论】:

  • 如果您能给我们一些背景信息,那就太好了。为什么会出现预期的分段错误?我很想知道一个正常运行的程序会产生分段错误的上下文。
  • 我将分享摘要......通过网络接收的一些消息的编码和解码过程是使用代码生成器生成的。有时会收到这样的消息,但其解码处理不当。在这样的场景中会出现分段错误。在代码中编写安全检查将是很多代码(一旦生成器下次生成代码,这些代码将被覆盖)。所以....
  • 您处理解码错误的方式行不通。未指向有效内存的指针不一定会在取消引用时产生分段错误;尤其是当它指向刚刚超出结构的边界时,它更有可能只是破坏数据。请尝试想一种不同的方法来处理错误的输入。你试图做的是灾难的秘诀。
  • 实际上这与双重释放问题有关,而不是一些随机内存指针。所以它总是导致分段。每当有一些随机消息时,很少有指针被双重释放重要我也很想知道是否有办法解决这种情况
  • 不应该在信号处理程序中使用 printf() 和朋友,它不是信号安全的。 (在这种情况下,它实际上可能会使您的问题恶化)

标签: c linux process segmentation-fault signals


【解决方案1】:

没有办法用股票malloc 做到这一点。没有可移植的工具可让您跟踪自某个时间点以来已完成的分配。

您可以这样做:创建一个包装malloc 的函数,并将每个新分配的内存区域添加到链接列表中。当你需要清除内存泄漏时,遍历这个列表和free你在那里找到的所有块。当然,这只有在您可以保证没有指向已分配区域的指针时才有效。

重新设计您的控制流可能是个好主意,这样在您想要中止控制的时候就不会发生内存分配。

【讨论】:

    猜你喜欢
    • 2021-02-21
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    • 2011-11-29
    • 1970-01-01
    • 2011-01-12
    • 2014-08-16
    • 2015-02-27
    相关资源
    最近更新 更多