通常在程序挂掉的时候我们会catch 他们挂掉的signal,然后在signal中打印出当时的一个stack,来方便问题调查, 但是在stack overflow的情况发生时,会没有拿到stack。signal的stack也是建立在thread的调用栈上的,在overflow的情况下,stack没有足够的空间来执行signal处理函数,signal处理函数就会被忽略。


示例代码:
main 主程序

#include <signal.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include "mybacktrace.h" void recursiondeath()
{
  char buffer[];
  recursiondeath();
  memset(buffer, 0xeb, sizeof(buffer));
  printf("%d", buffer[]);
} void* threadloop(void* args)
{
  // using sginal stack
  char altstack[SIGSTKSZ];
  addsignalstack(altstack, SIGSTKSZ);   recursiondeath();
  return NULL;
} int main(int argc, char const *argv[])
{
  char altstack[SIGSTKSZ];
  registersignal();
  addsignalstack(altstack, SIGSTKSZ);   pthread_t t;
  pthread_create(&t, NULL, threadloop, NULL);   pthread_join(t, NULL);   return ;
}

mybacktrace.h 头文件

#include <execinfo.h>
#include <signal.h>
#include <assert.h> void signalhandler(int sig)
{
printf("signal revived [%d]\n", sig);
// get the back trace
enum {
MAX_STACK = ,
}; void *stack[MAX_STACK];
int size = backtrace(stack, MAX_STACK);
if(size == ) {
printf("fail to get backtrace\n");
}
char** strs = backtrace_symbols(stack, size);
int i = ;
for (i = ; i < size; ++i) {
printf("%s\n", strs[i]);
}
free(strs); signal(sig, SIG_DFL);
} void addsignalstack(char *stack, int size)
{
assert(stack!=NULL);
// using sginal stack
stack_t sigstack;
sigstack.ss_sp = stack;
sigstack.ss_size = SIGSTKSZ;
sigstack.ss_flags = ;
if (sigaltstack(&sigstack, ) < ) {
perror("sig stack setting failed");
}
} void registersignal()
{
struct sigaction act;
act.sa_handler = signalhandler;
act.sa_flags = SA_ONSTACK|SA_RESTART; int ret = sigaction(SIGSEGV, &act, NULL);
if (ret < ) {
perror("sigaction failed\n");
} ret = sigaction(SIGBUS, &act, NULL);
if (ret < ) {
perror("sigaction failed\n");
} ret = sigaction(SIGILL, &act, NULL);
if (ret < ) {
perror("sigaction failed\n");
} }

说明:
添加signal alt stack

void addsignalstack(char *stack, int size)
{
assert(stack!=NULL);
// using sginal stack
stack_t sigstack;
sigstack.ss_sp = stack;
sigstack.ss_size = SIGSTKSZ;
sigstack.ss_flags = ;
if (sigaltstack(&sigstack, ) < ) {
perror("sig stack setting failed");
}
}

这边由外部传进来的数组作为signal 处理函数执行用的stack
注册signal函数:
```

void registersignal()
{
  struct sigaction act;
  act.sa_handler = signalhandler;
  act.sa_flags = SA_ONSTACK|SA_RESTART;   int ret = sigaction(SIGSEGV, &act, NULL);
  if (ret < ) {
    perror("sigaction failed\n");
  }   ret = sigaction(SIGBUS, &act, NULL);
  if (ret < ) {
    perror("sigaction failed\n");
  }   ret = sigaction(SIGILL, &act, NULL);
  if (ret < ) {
    perror("sigaction failed\n");
  }
}

注册了signal
SIGSEGV
SIGBUS
SIGILL
另外sigaction flag添加了SA_ONSTACK,确保当signal发生的时候,
signal处理函数会将sig atl stack作为函数frame


主函数:

int main(int argc, char const *argv[])
{
char altstack[SIGSTKSZ];
registersignal();
addsignalstack(altstack, SIGSTKSZ); pthread_t t;
pthread_create(&t, NULL, threadloop, NULL); pthread_join(t, NULL); return ;
}

执行前添加下signal的altstak,这里使用栈上的数组来作为signal处理函数的函数栈,可以通过malloc或者mmap分配.


线程的主函数

void* threadloop(void* args)
{
// using sginal stack
char altstack[SIGSTKSZ];
addsignalstack(altstack, SIGSTKSZ); recursiondeath();
return NULL;
}

执行前再添加下sig alt stack
注意:sig alt stack时每个线程自己单独的属性,所以每个线程都需要添加自己的sig alt stack

pthread中如何追踪stack over flow的更多相关文章

  1. 转载~kxcfzyk:Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解

    Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解   多线程c语言linuxsemaphore条件变量 (本文的读者定位是了解Pthread常用多线程API和Pthread互斥锁 ...

  2. <s:property="a" value=""/>取的<s:debug></s:debug>中的value stack中的属性值

    <s:property="a"  value=""/>取的<s:debug></s:debug>中的value stack中 ...

  3. 操作系统中 heap 和 stack 的区别

    操作系统中 heap 和 stack 的区别heap 和 stack是什么堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.==在单片机 ...

  4. 在onelogin中使用OpenId Connect Implicit Flow

    目录 简介 OpenId Implicit Flow 创建onelogin的配置 页面的运行和请求流程 关键代码 总结 简介 onelogin支持多种OpenId Connect的连接模式,上一篇文章 ...

  5. pthread中取消线程

    取消线程:告诉一个线程关掉自己,取消操作允许线程请求终止其所在进程中的任何其他线程.不希望或不需要对一组相关的线程执行进一步操作时,可以选择执行取消操作.取消线程的一个示例是异步生成取消条件. 对于c ...

  6. java中Set,Map,Stack一些简单用法

    import java.util.Iterator; import java.util.Stack; import java.io.*; import java.util.Set; import ja ...

  7. C#中泛型容器Stack<T>

    我以前都是学出c,c++,这个学期开始学c#有点不适应,在编程中遇到些问题,所以自己在网上查了些资料,翻了一下书,写一些总结. 关于c#中Stack<T>泛型容器: <1>st ...

  8. Knockoutjs官网翻译系列(四) computed中依赖追踪是如何工作的

    初学者无需了解这些 ,但是很多高级程序员想知道我们为什么可以保持跟踪这些依赖以及可以正确的更新到UI中.它其实很简单.跟踪算法是这样的: 无论何时你定义了一个computed observable,K ...

  9. 解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法

    堆区:专门用来保存对象的实例(new 创建的对象和数组),实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在Stack中) 1.存储的全部是对象 ...

随机推荐

  1. 使用POI导出excel进阶篇

    进阶篇就是涉及到合并单元格了.就是某一列相同的单元格需要合并为一个,并分为多个sheet. 效果如图: 直接上代码,需要提供的数据自己搞,传到工具类里面就好. JcExcelVoSuper.java ...

  2. bzoj 3028 食物——生成函数

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3028 把式子写出来,化一化,变成 x / ((1-x)^4) ,变成几个 sigma 相乘的 ...

  3. 蓝桥杯 算法训练 ALGO-149 5-2求指数

     算法训练 5-2求指数   时间限制:1.0s   内存限制:256.0MB 问题描述 已知n和m,打印n^1,n^2,...,n^m.要求用静态变量实现.n^m表示n的m次方.已知n和m,打印n^ ...

  4. 机器学习:SVM(非线性数据分类:SVM中使用多项式特征和核函数SVC)

    一.基础理解 数据:线性数据.非线性数据: 线性数据:线性相关.非线性相关:(非线性相关的数据不一定是非线性数据) 1)SVM 解决非线性数据分类的方法 方法一: 多项式思维:扩充原本的数据,制造新的 ...

  5. java代码用continue输出奇数——————————

    总结:continue用法是:在for,do-while.while循环中 并且,continue的意思是跳出循环的剩余部分,进行下一次循环.不是下一步循环 package com.b; import ...

  6. java代码异常,水位异常的捕获

    总: 异常的产生!!!!异常如何实现,继承~~~ package com.b; //我不懂为什么这里的异常一定要来自于父类.子类.去继承它.因为Exception是Throwable类的子类异常类.而 ...

  7. java代码随机数100个,10个一输出显示======

    总结:空格???懂否?如何显示 for(int i=0;i<100;i++){ if(i%10==0){ System.out.println(); } System.out.print(n[i ...

  8. POJ 1276 Cash Machine(单调队列优化多重背包)

    Cash Machine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 38986   Accepted: 14186 De ...

  9. 杂项:VS调试技巧之附加进程

    ylbtech-杂项:VS调试技巧之附加进程 1. 摘录返回顶部 1. 用过VS一段时间的程序员们相信都有过这种调试经历:每次按下F5进行断点调试时,都要等待好长时间:先让解决方式编译通过,然后启动V ...

  10. mycat 新增分片和字符集

    执行 select * from travelrecord ,分析Debug日志,说明整个执行逻辑,包括连接获取,连接同步信息,数据合并,数据返回,连接释放 新增一个分片表 T_VOTE (ID,PR ...