怎样找到错误(段错误,内存错误)到底发生哪一行?

leinchu 2010-05-19 07:04:10
我写一个比较复杂的epoll的多线程的socket程序,并且要和memcache服务,mysql数据这些都有联系

所以随着功能越多越多,出问题就越来越难以找出来,问题很有可能不止在一个地方;

我用了memwatch,感觉帮助不大;

用信号处理,捕获内存错误,然后用下面的代码"把程序交给"gdb,但是gdb 最多也就用个bt,可以知道在哪个函数出的问题,但是还是不知道哪行,哪个变量出问题了.


void dump(int signo)
{
long now=Time();
printf("This is DUMP %d-------------------------\n",now);
char buf[1024];
char cmd[1024];
FILE *fh;

snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());
if(!(fh = fopen(buf, "r")))
exit(0);
if(!fgets(buf, sizeof(buf), fh))
exit(0);
fclose(fh);
if(buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
snprintf(cmd, sizeof(cmd), "gdb %s %d", buf, getpid());
system(cmd);
//dolog(cmd);
printf("This is DUMP -------------------------\n");
ctMeme++;
exit(0);
}


很多人似乎都用gdb,但是我感觉对于多线程的,gdb根本无能为力啊

请各位有好方法,技巧的,都不吝赐教!

谢谢!
...全文
644 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
野男孩 2010-05-22
  • 打赏
  • 举报
回复
先用日志或者gdb确定出错行吧。

确定了哪一行,再分析这一行中可能的错误,一个个分析,一个个排查。
主要就是指针是否为空,是否指向有效的内存地址的问题。
leinchu 2010-05-22
  • 打赏
  • 举报
回复
总结一下:

1 先调通单线程
2 gdb出错之后用where可以知道大概出错的位置
beginsoft_nj 2010-05-21
  • 打赏
  • 举报
回复
我以前也经常碰到这个段错误 大部分都是因为内存越界或使用无效指针造成的 楼主最好先看看有没有内存越界或者使用空指针的情况
KevinHo 2010-05-21
  • 打赏
  • 举报
回复
LZ, 试试先单线程,然后出问题了就单步运行看看。
yanran_hill 2010-05-21
  • 打赏
  • 举报
回复
开发大的应用程序,首先需要注意的就是如何保证模块具有很好的可测试性,其次才是代码的效率和完成的功能.在编写代码以前,最好仔细想一想应该采用哪些调试手段,在完成模块代码的同时,也完成测试代码
leinchu 2010-05-21
  • 打赏
  • 举报
回复
我在网上找到了一个try catch

但是不知道怎么用

http://notownme.javaeye.com/blog/94540

赵4老师 2010-05-19
  • 打赏
  • 举报
回复
多线程别忘了在适当的地方加锁。
rwjlqn 2010-05-19
  • 打赏
  • 举报
回复
额一般都记录日志的~
向立天 2010-05-19
  • 打赏
  • 举报
回复
我一般采用的方法是屏蔽代码测试
有一个朋友他自己做了一个output窗口
可以在程序中添加一些语句把自己关心的调试信息传出来
zhangyafei13 2010-05-19
  • 打赏
  • 举报
回复
来看看,学习学习
老马何以识途 2010-05-19
  • 打赏
  • 举报
回复
我的做法也是写日志,一步步的缩小范围。减少线程数也是好办法,可以较快的定位出错位置。
lzx_ok 2010-05-19
  • 打赏
  • 举报
回复
如果是线程,最好先把单线程的调通再说了

。。。
lin_style 2010-05-19
  • 打赏
  • 举报
回复
#define malloc malloc_proxy(__FILE__ , __LINE__)

malloc_f
malloc_proxy(const char *filename, int line)
{
g_filename = filename;
g_line = line;

return malloc;
}


调试输出g_filename,g_line.
dongnanfanlin 2010-05-19
  • 打赏
  • 举报
回复
gdb中单步调试,打印每个变量值,查看是否有问题
lys0310 2010-05-19
  • 打赏
  • 举报
回复
数组越界?


void dump(int signo)
{
long now=Time();
printf("This is DUMP %d-------------------------\n",now);
char buf[1024];
char cmd[1024];
FILE *fh;

snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());
if(!(fh = fopen(buf, "r")))
exit(0);

//可能因大于1024越界
if(!fgets(buf, sizeof(buf), fh))
exit(0);
fclose(fh);

// buf[strlen(buf) - 1] == '\n'不正确吧?
//C语言以'\0'作为字符串结束标记
//此处也有可能越界!!
if(buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
snprintf(cmd, sizeof(cmd), "gdb %s %d", buf, getpid());
system(cmd);
//dolog(cmd);
printf("This is DUMP -------------------------\n");
ctMeme++;
exit(0);
}


james_hw 2010-05-19
  • 打赏
  • 举报
回复
1、调试需要耐心,lz可能是第一次写较大的模块,以后就会适应了
2、内存越界的问题一直比较头痛,先用lint检查自己的代码,确保代码是正确的,其次增加打印信息,最好每一个动作都在打印,不要嫌麻烦,有经验和无经验的差别就在这里,这个在调试和测试阶段定位问题非常有用
3、对异常记录日志,这个主要用于出场的产品,因为内存可以保存的日志数量有限,因此主要用于严重影响设备的异常故障,一般来说内存越界等问题要在步骤2排除完,如果遗留到出场产品,后果十分严重。
sfd1234 2010-05-19
  • 打赏
  • 举报
回复
不知道,没到这个高度!
ZangXT 2010-05-19
  • 打赏
  • 举报
回复
gdb,段错误后用where命令。
sky198306 2010-05-19
  • 打赏
  • 举报
回复
个人意见先单线程调试,然后再组合,根据日志判断
cattycat 2010-05-19
  • 打赏
  • 举报
回复
gdb调试也是跟进具体哪个函数中,多线程的函数中。
如果出现段错误,看能不能保存dump的core文件,根据这个调试。
还有就是按楼上说的增加日志,根据输出判断大致位置。
加载更多回复(6)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧