QQ号没有了qq我的状态怎么没了办啊?

coredump文件夹占的很,能删吗
全部答案(共2个回答)
,手留余香,如若,您对我的答复满意,请选择“好评”,谢谢您的采纳)
方法一:将C盘空间释放出来,但它也有弊端,就是用它释放完后,过一会会C盘又重新满了,这种方法是:
1、win键+X ,选择 “命令提示符(管理员)(A)”
XP系统减肥的步骤:
1.打开“我的电脑”-“工具”-“文件夹选项”-“查看”-在“显示所有文件和文件夹”选项前打勾-“确定”;
2.删除以下文...
这些文件不要删除,都是属于系统文件,内存16g应该够用了
遇到这种问题
首先考虑病毒、木马、恶意软件
杀毒、杀木马、杀恶意软件
工具这里找:
都是免费的、正版的、自动升级的
卡巴杀毒、AVG Anti-...
这里有一个,你去研究把:
[url] [/url]
大家还关注
电脑快捷方式指向更改,打不开 我电脑桌面...
确定举报此问题
举报原因(必选):
广告或垃圾信息
激进时政或意识形态话题
不雅词句或人身攻击
侵犯他人隐私
其它违法和不良信息
报告,这不是个问题
报告原因(必选):
这不是个问题
这个问题分类似乎错了
这个不是我熟悉的地区分析GetStackTrace
确认core的详细位置:
# core在该指令
0xd145 &_Z13GetStackTracePPvii+21&: mov
0x8(%rax),%r9
(gdb) p/x $rip
# core 的指令位置
$9 = 0x45d145
(gdb) p/x $rax
$10 = 0x4e73aa58
(gdb) x/1a $rax+0x8
# rax + 8 = 0x4e73aa60
0x4e73aa60:
该指令尝试从[0x4e73aa60]处读取内容,然后出错,这个内存单元不可读。但是具体这个指令在代码中是什么意思,需要将这个指令对应到代码中。获取tcmalloc的源码,发现GetStackTrace根据编译选项有很多实现,所以这里选择最可能的实现,然后对比汇编以确认代码是否匹配。最初选择的是stacktrace_x86-64-inl.h,后来发现完全不匹配,又选择了stacktrace_x86-inl.h。这个实现版本里也有对64位平台的支持。
stacktrace_x86-inl.h里使用了一些宏来生成函数名和参数,精简后代码大概为:
int GET_STACK_TRACE_OR_FRAMES {
void **sp;
unsigned long rbp;
__asm__ volatile ("mov %%rbp, %0" : "=r" (rbp));
sp = (void **) rbp;
int n = 0;
while (sp && n & max_depth) {
if (*(sp+1) == reinterpret_cast&void *&(0)) {
void **next_sp = NextStackFrame&!IS_STACK_FRAMES, IS_WITH_CONTEXT&(sp, ucp);
if (skip_count & 0) {
skip_count--;
result[n] = *(sp+1);
sp = next_sp;
NextStackFrame是一个模板函数,包含一大堆代码,精简后非常简单:
template&bool STRICT_UNWINDING, bool WITH_CONTEXT&
static void **NextStackFrame(void **old_sp, const void *uc) {
void **new_sp = (void **) *old_sp;
if (STRICT_UNWINDING) {
if (new_sp &= old_sp) return NULL;
if ((uintptr_t)new_sp - (uintptr_t)old_sp & 100000) return NULL;
if (new_sp == old_sp) return NULL;
if ((new_sp & old_sp)
&& ((uintptr_t)new_sp - (uintptr_t)old_sp & 1000000)) return NULL;
if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
return new_sp;
上面这个代码到汇编的对比过程还是花了些时间,其中汇编中出现的一些常量可以大大缩短对比时间,例如上面出现了100000,汇编中就有:
0xd176 &_Z13GetStackTracePPvii+70&: cmp
$0x186a0,%rbx
注意NextStackFrame中的 if (STRICT_UNWINDING)使用的是模板参数,这导致生成的代码中根本没有else部分,也就没有1000000这个常量
在对比代码的过程中,可以知道关键的几个寄存器、内存位置对应到代码中的变量,从而可以还原core时的现场环境。分析过程中不一定要从第一行汇编读,可以从较明显的位置读,从而还原整个代码,函数返回指令、跳转指令、比较指令、读内存指令、参数寄存器等都是比较明显对应的地方。
另外注意GetStackTrace在RecordGrowth中调用,传入了3个参数:
GetStackTrace(t-&stack, kMaxStackDepth-1, 3); // kMaxStackDepth = 31
以下是我分析的简单注解:
(gdb) disassemble
Dump of assembler code for function _Z13GetStackTracePPvii:
0xd130 &_Z13GetStackTracePPvii+0&:
0xd131 &_Z13GetStackTracePPvii+1&:
0xd134 &_Z13GetStackTracePPvii+4&:
0xd135 &_Z13GetStackTracePPvii+5&:
0xd138 &_Z13GetStackTracePPvii+8&:
0xd13b &_Z13GetStackTracePPvii+11&: test
0xd13e &_Z13GetStackTracePPvii+14&: je
0x45d167 &_Z13GetStackTracePPvii+55&
0xd140 &_Z13GetStackTracePPvii+16&: cmp
# while ( .. max_depth & n ?
0xd143 &_Z13GetStackTracePPvii+19&: jge
0x45d167 &_Z13GetStackTracePPvii+55&
0xd145 &_Z13GetStackTracePPvii+21&: mov
0x8(%rax),%r9
# 关键位置:*(sp+1) -& r9, rax 对应 sp变量
0xd149 &_Z13GetStackTracePPvii+25&: test
# *(sp+1) == 0 ?
0xd14c &_Z13GetStackTracePPvii+28&: je
0x45d167 &_Z13GetStackTracePPvii+55&
0xd14e &_Z13GetStackTracePPvii+30&: mov
(%rax),%rcx
# new_sp = *old_sp,这里已经是NextStackFrame的代码
0xd151 &_Z13GetStackTracePPvii+33&: cmp
# new_sp &= old_sp ?
0xd154 &_Z13GetStackTracePPvii+36&: jb
0x45d170 &_Z13GetStackTracePPvii+64&
# new_sp & old_sp 跳转
0xd156 &_Z13GetStackTracePPvii+38&: xor
0xd158 &_Z13GetStackTracePPvii+40&: test
# skip_count & 0 ?
0xd15a &_Z13GetStackTracePPvii+42&: jle
0x45d186 &_Z13GetStackTracePPvii+86&
0xd15c &_Z13GetStackTracePPvii+44&: sub
# skip_count--
0xd15f &_Z13GetStackTracePPvii+47&: mov
0xd162 &_Z13GetStackTracePPvii+50&: test
# while (sp ?
0xd165 &_Z13GetStackTracePPvii+53&: jne
0x45d140 &_Z13GetStackTracePPvii+16&
0xd167 &_Z13GetStackTracePPvii+55&: pop
0xd168 &_Z13GetStackTracePPvii+56&: leaveq
0xd169 &_Z13GetStackTracePPvii+57&: mov
# r8 存储了返回值,r8=n
0xd16c &_Z13GetStackTracePPvii+60&: retq
# return n
0xd16d &_Z13GetStackTracePPvii+61&: nopl
0xd170 &_Z13GetStackTracePPvii+64&: mov
0xd173 &_Z13GetStackTracePPvii+67&: sub
# offset = new_sp - old_sp
0xd176 &_Z13GetStackTracePPvii+70&: cmp
$0x186a0,%rbx
# offset & 100000 ?
0xd17d &_Z13GetStackTracePPvii+77&: ja
0x45d156 &_Z13GetStackTracePPvii+38& # return NULL
0xd17f &_Z13GetStackTracePPvii+79&: test
# new_sp & (sizeof(void*) - 1)
0xd182 &_Z13GetStackTracePPvii+82&: je
0x45d158 &_Z13GetStackTracePPvii+40&
0xd184 &_Z13GetStackTracePPvii+84&: jmp
0x45d156 &_Z13GetStackTracePPvii+38&
0xd186 &_Z13GetStackTracePPvii+86&: movslq %r8d,%rax
0xd189 &_Z13GetStackTracePPvii+89&: add
0xd18d &_Z13GetStackTracePPvii+93&: mov
%r9,(%rdi,%rax,8)# 关键位置:result[n] = *(sp+1)
0xd191 &_Z13GetStackTracePPvii+97&: jmp
0x45d15f &_Z13GetStackTracePPvii+47&
分析过程比较耗时,同时还可以分析下GetStackTrace函数的实现原理,其实就是利用RBP寄存器不断回溯,从而得到整个调用堆栈各个函数的地址(严格来说是返回地址)。简单示意下函数调用中RBP的情况:
saved registers
# i.e push rbx
local variabes
# i.e sub 0x10, rsp
return address
# call xxx
last func RBP
# mov rsp, rbp
saved registers
local variables
return address
last func RBP
总之,一般情况下,任何一个函数中,RBP寄存器指向了当前函数的栈基址,该栈基址中又存储了调用者的栈基址,同时该栈基址前面还存储了调用者的返回地址。所以,GetStackTrace的实现,简单来说大概就是:
// 取得当前函数GetStackTrace的栈基址
while (n & max_depth) {
new_sp = *sp
result[n] = *(new_sp+1)
以上,最终就知道了以下关键信息:
r8 对应变量 n,表示当前取到第几个栈帧了
rax 对应变量 sp,代码core在 *(sp+1)
rdi 对应变量 result,用于存储取得的各个地址
然后可以看看现场是怎样的:
(gdb) x/10a $rdi
0x1ffc9b98:
0x45a088 &_ZN8tcmalloc15CentralFreeList18FetchFromSpansSafeEv+40&
0x45a10a &_ZN8tcmalloc15CentralFreeList11RemoveRangeEPPvS2_i+106&
0x1ffc9ba8:
0x45c282 &_ZN8tcmalloc11ThreadCache21FetchFromCentralCacheEmm+114&
0x470766 &tc_malloc+790&
0x1ffc9bb8:
0x7f7 &__conhash_get_rbnode+34&
0x1ffc9bc8:
0x1ffc9bd8:
(gdb) p/x $r8
(gdb) p/x $rax
$4 = 0x4e73aa58
GetStackTrace在取调用__conhash_get_rbnode的函数时出错,取得了5个函数地址。当前使用的RBP为0x4e73aa58。
RBP也是从堆栈中取出来的,既然这个地址有问题,首先想到的就是有代码局部变量/数组写越界。例如sprintf的使用。而且,一般写越界破坏堆栈,都可能是把调用者的堆栈破坏了,例如:
char s[32];
memcpy(s, p, 1024);
因为写入都是从低地址往高地址写,而调用者的堆栈在高地址。当然,也会遇到写坏调用者的调用者的堆栈,也就是跨栈帧越界写,例如以前遇到的:
len = vsnprintf(buf, sizeof(buf), fmt, wtf-long-string);
buf[len] = 0;
__conhash_get_rbnode的RBP是在tcmalloc的堆栈中取的:
0x0766 in tc_malloc ()
(gdb) x/10a $rsp
0x4e738b80:
0x4e73aa58
0x22c86870
0x4e738b90:
0x4e738bd0
0x4e738ba0:
0x4e73aa58
0x7f7 &__conhash_get_rbnode+34&
# 0x4e73aa58
所以这里就会怀疑是tcmalloc这个函数里有把堆栈破坏,这个时候就是读代码,看看有没有疑似危险的地方,未果。这里就陷入了僵局,怀疑又遇到了跨栈帧破坏的情况,这个时候就只能__conhash_get_rbnode调用栈中周围的函数翻翻,例如调用__conhash_get_rbnode的函数__conhash_add_replicas中恰好有字符串操作:
void __conhash_add_replicas(conhash_t *conhash, int32_t iden)
node_t* node = __conhash_create_node(iden, conhash-&replica);
char buf[buf_len]; // buf_len = 64
snprintf(buf, buf_len, VIRT_NODE_HASH_FMT, node-&iden, i);
uint32_t hash = conhash-&cb_hashfunc(buf);
if(util_rbtree_search(&(conhash-&vnode_tree), hash) == NULL)
util_rbtree_node_t* rbnode = __conhash_get_rbnode(node, hash);
这段代码最终发现是没有问题的,这里又耗费了不少时间。后来发现若干个函数里的RBP都有点奇怪,这个调用栈比较正常的范围是:0x4e738c90
0xcd4c2 in __conhash_get_rbnode (node=0x22c86870, hash=30)
(gdb) p/x $rbp
$6 = 0x4e73aa58
# 这个还不算特别可疑
0xcd76e in __conhash_add_replicas (conhash=0x24fbc7e0, iden=&value optimized out&)
(gdb) p/x $rbp
$7 = 0x4e738c60
# 这个也不算特别可疑
(gdb) f 10
#10 0xcd1fa in conhash_add_node (conhash=0x24fbc7e0, iden=0) at build/release64/cm_sub/conhash/conhash.c:72
(gdb) p/x $rbp
(gdb) f 11
#11 0xc651b in cm_sub::TopoCluster::initLBPolicyInfo (this=0x)
(gdb) p/x $rbp
$9 = 0x2598fef0
为什么很多函数中RBP都看起来不正常? 想了想真要是代码里把堆栈破坏了,这错误得发生得多巧妙?
错误RBP的来源
然后转机来了,脑海中突然闪出-fomit-frame-pointer。编译器生成的代码中是可以不需要栈基址指针的,也就是RBP寄存器不作为栈基址寄存器。大部分函数或者说开启了frame-pointer的函数,其函数头都会有以下指令:
表示保存调用者的栈基址到栈中,以及设置自己的栈基址。看下__conhash系列函数;
Dump of assembler code for function __conhash_get_rbnode:
0xcd4a0 &__conhash_get_rbnode+0&:
%rbx,-0x18(%rsp)
0xcd4a5 &__conhash_get_rbnode+5&:
%rbp,-0x10(%rsp)
这个库是单独编译的,没有显示指定-fno-omit-frame-pointer,查阅,o2优化是开启了omit-frame-pinter 的。
在没有RBP的情况下,tcmalloc的GetStackTrace尝试读RBP取获取调用返回地址,自然是有问题的。但是,如果整个调用栈中的函数,要么有RBP,要么没有RBP,那么GetStackTrace取出的结果最多就是跳过一些栈帧,不会出错。 除非,这中间的某个函数把RBP寄存器另作他用(编译器省出这个寄存器肯定是要另作他用的)。所以这里继续追查这个错误地址0x4e73aa58的来源。
来源已经比较明显,肯定是__conhash_get_rbnode中设置的,因为这个函数的RBP是在被调用者tcmalloc中保存的。
Dump of assembler code for function __conhash_get_rbnode:
0xcd4a0 &__conhash_get_rbnode+0&:
%rbx,-0x18(%rsp)
0xcd4a5 &__conhash_get_rbnode+5&:
%rbp,-0x10(%rsp)
0xcd4aa &__conhash_get_rbnode+10&:
# 改写了RBP
0xcd4ac &__conhash_get_rbnode+12&:
%r12,-0x8(%rsp)
0xcd4b1 &__conhash_get_rbnode+17&:
$0x18,%rsp
0xcd4b5 &__conhash_get_rbnode+21&:
0xcd4b8 &__conhash_get_rbnode+24&:
$0x30,%edi
0xcd4bd &__conhash_get_rbnode+29&:
0x7f &malloc@plt&
# 调用tcmalloc,汇编到这里即可
这里打印RSI寄存器的值可能会被误导,因为任何时候打印寄存器的值可能都是错的,除非它有被显示保存。不过这里可以看出RSI的值来源于参数(RSI对应第二个参数):
void __conhash_add_replicas(conhash_t *conhash, int32_t iden)
node_t* node = __conhash_create_node(iden, conhash-&replica);
char buf[buf_len]; // buf_len = 64
snprintf(buf, buf_len, VIRT_NODE_HASH_FMT, node-&iden, i);
uint32_t hash = conhash-&cb_hashfunc(buf); // hash值由一个字符串哈希函数计算
if(util_rbtree_search(&(conhash-&vnode_tree), hash) == NULL)
util_rbtree_node_t* rbnode = __conhash_get_rbnode(node, hash);
追到__conhash_add_replicas:
0xcd764 &__conhash_add_replicas+164&:
# 来源于rbx
0xcd766 &__conhash_add_replicas+166&:
0xcd769 &__conhash_add_replicas+169&:
0x7f &__conhash_get_rbnode@plt&
(gdb) p/x $rbx
$11 = 0x4e73aa58
(gdb) p/x hash
$12 = 0x4e73aa58
# 0x4e73aa58
找到了0x4e73aa58的来源。这个地址值竟然是一个字符串哈希算法算出来的!这里还可以看看这个字符串的内容:
(gdb) x/1s $rsp
0x4e738bd0:
"conhash-"
这个碉堡的哈希函数是conhash_hash_def。
coredump的条件
以上,既然只要某个库omit-frame-pointer,那tcmalloc就可能出错,为什么发生的频率并不高呢?这个可以回到GetStackTrace尤其是NextStackFrame的实现,其中包含了几个合法RBP的判定:
if (new_sp &= old_sp) return NULL;
// 上一个栈帧的RBP肯定比当前的大
if ((uintptr_t)new_sp - (uintptr_t)old_sp & 100000) return NULL; // 指针值范围还必须在100000内
if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL; // 由于本身保存的是指针,所以还必须是sizeof(void*)的整数倍,对齐
有了以上条件,才使得这个core几率变得很低。
最后,如果你很熟悉tcmalloc,整个问题估计就被秒解了:
另外附上另一个有意思的东西。
在分析__conhash_add_replicas时,其内定义了一个64字节的字符数组,查看其堆栈:
(gdb) x/20a $rsp
0x4e738bd0:
# 这些是字符串conhash-
0x4e738be0:
0x4e738bf0:
0x7f75532cd69e &__conhash_create_node+78&
0x4e738c00:
0x24fbc7e0
0x4e738c60
0x4e738c10:
0x24fbc7e0
0x7f7 &__conhash_add_replicas+35&
0x4e738c20:
0x24fbc7e8
0x4e738c30:
0x4e738c20
0x24fbc7e0
0x4e738c40:
0x4e738c50:
0x4e738c60:
0x7f75532cd1fa &conhash_add_node+74&
最开始我觉得buf占64字节,也就是整个[0x4e738bd0, 0x4e738c10)内存,但是这块内存里居然有函数地址,这一度使我怀疑这里有问题。后来醒悟这些地址是定义buf前调用__conhash_create_node产生的,调用过程中写到堆栈里,调用完后栈指针改变,但并不需要清空栈中的内容。当前位置:&&技术问答>
segmentation fault(core dump)这句话怎么解释??
&&&&来源:&互联网& 发布时间:
&&&&本文导语:&
写了一个程序hoc3.c,编译后运行,出现如下错误提示:
./hoc3: out of memory near line 1
segmentation fault(core dump)
请问这个错误怎么解释?
我察看了程序很久都没查出来,是内存不够了吗?
写了一个程序hoc3.c,编译后运行,出现如下错误提示:
./hoc3: out of memory near line 1
segmentation fault(core dump)
请问这个错误怎么解释?
我察看了程序很久都没查出来,是内存不够了吗?
用gdb调一下
编译时记得用-g
gcc -g -o test test.c
然后gdb test回车
再bt下回车
就能看到你的程序当到那块了
这里列出了出栽过程./
段错误,一般是由于内存访问越界引起的。可以使用gdb调试core dump文件,查看程序是执行到什么地方出错的。
这个问题我经常碰到,一般是内存越界的问题 由内核发出的消息,你用gdb调试就会指导哪里出错了 我的错误是bcopy用的越界了
您可能感兴趣的文章:
本站()旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。本站()站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
相关文章推荐
特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!
(C)2012-,E-mail:www_169it_(请将#改为@)

我要回帖

更多关于 如何注册qq号 的文章

 

随机推荐