linux c/c++ 段错误(Segmentation fault 查找示例2)
来源:互联网 发布:现在淘宝开店赚钱吗 编辑:程序博客网 时间:2024/04/29 19:46
addr.h
#ifndef __ADDR_H_#define __ADDR_H_#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <fcntl.h>#include <errno.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <pthread.h>#include <unistd.h>#include <signal.h>#include <sys/time.h>#include <sys/resource.h>typedef enum{ NO, OK}Status_t;typedef struct{ pthread_t tid; pthread_mutex_t mutex; pthread_cond_t cond; int index; int i; char *buf; char date[12]; Status_t status;}thread_pool_t;void *thread_all(void *arg);int creat_threads(int num, thread_pool_t *pools);thread_pool_t * create_pools(int thread_num);int task_allocation(thread_pool_t * pools, int thread_num, int id);void wait_all_threads_ready(thread_pool_t *pools, int thread_num);#endif
addr.cpp
#include "addr.h"pthread_attr_t attr;#define THREAD_STACK_SIZE 16*1024void *thread_all(void *arg){ thread_pool_t *worker = (thread_pool_t *)arg; int b= 5; while (1) { pthread_mutex_lock(&worker->mutex); while (worker->status == NO) pthread_cond_wait(&worker->cond, &worker->mutex); worker->status = NO; if (!worker->i){ *(worker->buf) = 1; }else if (worker->i == 1){ //strcpy(worker->date, "hello world"); printf("hello\n"); printf("%s\n", b); }else if (worker->i == 2){ printf("%s\n", worker->i); }else printf("\n%lu i=%d hello world\n", pthread_self(), worker->i); pthread_mutex_unlock(&worker->mutex); }}int creat_threads(int num, thread_pool_t *pools){ int i = 0, ret = 0; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE); for (i; i < num; i++){ ret = pthread_create(&pools[i].tid, &attr, thread_all, (void *)(pools + i)); if (ret) { fprintf(stderr, "pthread_create:%s\n", strerror(ret)); return ret; } } return 0;}thread_pool_t * create_pools(int thread_num){ int i = 0; thread_pool_t * pools = (thread_pool_t *)malloc(sizeof(thread_pool_t)*thread_num); if (pools == NULL) { perror("malloc!\n"); return NULL; } for (i; i < thread_num; i++){ pthread_mutex_init(&pools[i].mutex, NULL); pthread_cond_init(&pools[i].cond, NULL); pools[i].index = i+1; pools[i].i = 0; pools[i].buf = NULL; pools[i].status = NO; } return pools;}int task_allocation(thread_pool_t * pools, int i, int id){ pthread_mutex_lock(&pools[i].mutex); pools[i].status = OK; pools[i].i = id; pthread_cond_signal(&pools[i].cond); pthread_mutex_unlock(&pools[i].mutex); return 0;}void wait_all_threads_ready(thread_pool_t *pools, int thread_num){ int i, flag; for (i = 0; i < thread_num; i++) { flag = 0; pthread_mutex_lock(&pools[i].mutex); if (pools[i].status == OK) { flag = 1; } pthread_mutex_unlock(&pools[i].mutex); if (flag) i--; }}
main.cpp
#include "addr.h"#include <execinfo.h>#include <libunwind.h>#include <dlfcn.h>#include <link.h>#define THREADNUM 10void sigaction_handler(int s, siginfo_t *info, void* cont){ int ret; void *buf[100]; ret = backtrace(buf, 100); backtrace_symbols_fd(buf, ret, 1); printf("the err addr:%#x\n", (size_t)info->si_addr); void *p = __builtin_return_address(0); printf("%p\n", p); p = __builtin_return_address(1); printf("%p\n", p); exit(0);}void sigaction_handler1(int s, siginfo_t *info, void* cont){ char name[256]; unw_cursor_t cursor; unw_context_t uc; unw_word_t ip, sp, offp; //Dl_info info; unw_getcontext(&uc); unw_init_local(&cursor, &uc); while (unw_step(&cursor) > 0) { int line = 0; name[0] = '\0'; unw_get_proc_name(&cursor, name, 256, &offp); unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); printf ("name = %s, ip = %#x, sp = %#x\n", name, (long) ip, (long) sp); // if (dladdr((void *)ip, &info)){ // printf("%s %#x\n", info.dli_fname, info.dli_fbase); // } } int ret; void *buf[100]; ret = backtrace(buf, 100); backtrace_symbols_fd(buf, ret, 1); exit(0);}static intcallback(struct dl_phdr_info *info, size_t size, void *data){ int j; printf("name=%s (%d segments)\n", info->dlpi_name, info->dlpi_phnum); for (j = 0; j < info->dlpi_phnum; j++) printf("\t\t header %2d: address=%10p\n", j, (void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr)); return 0;}int main(int argc, char *argv[]){ int ret, id, i = 0; char buf[512]; thread_pool_t * pools; struct sigaction act; dl_iterate_phdr(callback, NULL); pools = create_pools(THREADNUM); if (!pools) { perror("create_pools!!\n"); return 1; } ret = creat_threads(THREADNUM, pools); if (ret) { perror("creat_threads!!\n"); return 1; } wait_all_threads_ready(pools, THREADNUM); act.sa_sigaction = sigaction_handler1; //act.sa_sigaction = sigaction_handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; //sigaction(SIGSEGV, &act, NULL); while(1){ printf("please input your id: "); fflush(stdout); ret = read(0, buf, sizeof(buf)); buf[ret - 1] = '\0'; id = atoi(buf); task_allocation(pools, i%THREADNUM, id); i++; } while (1) pause(); return 0;}
Makefile
CC = g++CPPFLAGS = -O0 -g3 -DDEBUG -DUNW_LOCAL_ONLY -D_GNU_SOURCEOBJLIB = libaddr.soaddr: main.cpp $(OBJLIB)$(CC) -rdynamic -I./ $(CPPFLAGS) -L./ -laddr -lpthread -L/usr/local/lib -lunwind -o $@ main.cpp$(OBJLIB):addr.cpp$(CC) -rdynamic -I./ $(CPPFLAGS) -fpic -shared -lpthread -o $@ $<.PHONY: cleanclean:rm -f addr $(OBJLIB)
程序采用多线程
ulimit -c 0 (当前shell 中不产生core文件)
第一步将main.cpp 中sigaction(SIGSEGV, &act, NULL); 注释, 这样段错误就会在内核日志产生相应信息
编译生成 addr、libaddr.so
运行./addr
程序打印:
name=libaddr.so (6 segments) header 0: address= 0xa24000 header 1: address= 0xa25000 header 2: address= 0xa25018 header 3: address= 0xa240f4 header 4: address= 0xa24df4 header 5: address= 0xa24000
输入0:
程序段错误结束
grep segfault /var/log/messages 查看
addr[22500]: segfault at 0 ip 00a24a21 sp b7724350 error 6 in libaddr.so[a24000+1000]
程序加载的基地址是0xa24000, crash 发生在进程调用的libaddr.so中
算偏移地址: 0x00a24a21 - 0xa24000 = 0xa21
一: addr2line -e libaddr.so 0xa21
二: objdump -DCl libaddr.so >dump
grep a21 dump 即可找到段错误发生位置
a19: 75 0b jne a26 <thread_all(void*)+0x76>
/mnt/hgfs/D/code/vm_proj_saving/myproj/addr2line/addr.cpp:19
a1b: 8b 45 f0 mov -0x10(%ebp),%eax
a1e: 8b 40 54 mov 0x54(%eax),%eax
a21: c6 00 01 movb $0x1,(%eax)
a24: eb 76 jmp a9c <thread_all(void*)+0xec>
错误发生在addr.cpp 19行
至于捕捉段错误信号将main.cpp 中sigaction(SIGSEGV, &act, NULL);注释去掉
分别act.sa_sigaction 分别赋值sigaction_handler和sigaction_handler1 编译运行体验一下
(注意一旦程序有捕捉这个信号了, 内核日志就不会在打印相印的错误信息了)
这里已sigaction_handler示例
编译运行:
./addr
打印动态库加载信息:
name=libaddr.so (6 segments)
header 0: address= 0xe22000
header 1: address= 0xe23000
header 2: address= 0xe23018
header 3: address= 0xe220f4
header 4: address= 0xe22df4
header 5: address= 0xe22000
输入0
程序段错误打印如下然后结束:
./addr(_Z17sigaction_handleriP7siginfoPv+0x1f)[0x8048ba3]
[0xf7440c]
/lib/libc.so.6[0x6a0b5f]
/lib/libc.so.6(_IO_vfprintf+0x3a6f)[0x66b49f]
/lib/libc.so.6(_IO_printf+0x30)[0x672470]
libaddr.so(_Z10thread_allPv+0xc9)[0xe22a79]
/lib/libpthread.so.0[0x7cda49]
/lib/libc.so.6(clone+0x5e)[0x709aae]
the err addr:0x2
0xf7440c
0x672470
libaddr.so(_Z10thread_allPv+0xc9)[0xe22a79] 指令地址0xe22a79
偏移地址: e22a79 - e22000 = a79
addr2line -e libaddr.so a79
得/mnt/hgfs/D/code/vm_proj_saving/myproj/addr2line/addr.cpp:25
- linux c/c++ 段错误(Segmentation fault 查找示例2)
- linux c/c++ 段错误(Segmentation fault 查找总结1)
- Linux段错误(Segmentation fault)
- C/C++中的段错误(Segmentation fault)
- C/C++中的段错误(Segmentation fault)
- C/C++中的段错误(Segmentation fault)
- C/C++中的段错误(Segmentation fault)
- C/C++中的段错误(Segmentation fault)
- C/C++中的段错误(Segmentation fault)[转]
- 段错误(segmentation fault)
- 段错误(segmentation fault)
- [转载]Linux下“段错误”--segmentation fault[]
- 关于linux的段错误(Segmentation fault)
- linux下segmentation fault(段错误)总结
- Segmentation Fault in Linux(段错误)
- Linux C程序:Segmentation fault
- segmentation fault(linux c)补遗
- 再谈Segmentation fault (core dumped)问题 -查找段错误原因
- Spring Batch 初始化数据,清空数据的做法
- eclipse设置
- SURF特征
- android获取外部存储和内部存储路径
- CSS3 backface-visibility 属性
- linux c/c++ 段错误(Segmentation fault 查找示例2)
- WampServer的配置
- 【Git入门之三】创建仓库
- SlidingMenu整合
- 查看锁和等待
- Java输出一个时间段内时间和星期对应关系
- REST标准,支持多终端。resteasy + spring + spring security + spring aop + hibernate + c# + jquery mobile
- 成为IT经理必备的十大软技能
- Robotium__xp/win7搭建测试环境