我有一个非常令人沮丧的问题。我的应用程序在几台机器上完美运行了一个月。 但是,由于段错误,我的应用程序几乎每天都会崩溃一台机器。 它总是在同一个指令地址崩溃:
segfault at 7fec33ef36a8 ip 000000000041c16d sp 00007fec50a55c80 error 6 in myapp[400000+f8000]
此地址指向memcpy
来电。
下面是我的应用程序摘录#1:
....
uint32_t size = messageSize - sizeof(uint64_t) + 1;
stack->trcData = (char*)Realloc(stack->trcData,(stack->trcSize + size + sizeof(uint32_t)));
char* buffer = stack->trcData + stack->trcSize;
uint32_t n_size = htonl(size);
memcpy(buffer,&n_size,sizeof(uint32_t)); /* ip 000000000041c16d points here*/
buffer += sizeof(uint32_t);
....
stack->trcSize += size + sizeof(uint32_t);
....
其中stack
是一个结构:
struct Stack{
char* trcData;
uint32_t trcSize;
/* ... some other elements */
};
和Realloc
是realloc
包装器:
#define Realloc(x,y) _Realloc((x),(y),__LINE__)
void* _Realloc(void* ptr,size_t size,int line){
void *tmp = realloc(ptr,size);
if(tmp == NULL){
fprintf(stderr,"R%i: Out of memory: trying to allocate: %lu.\n",line,size);
exit(EXIT_FAILURE);
}
return tmp;
}
messageSize
属于uint32_t
类型,其值始终大于44个字节。代码#1在循环中运行。 stack->trcData
只是一个缓冲区,它会收集一些数据,直到满足某些条件。 stack->trcData
始终初始化为NULL
。该应用程序使用gcc
编译,并启用了优化-O3
。当我在gdb
中运行它时,它当然没有像我预期的那样崩溃;)
我在my memcpy
通话期间崩溃了myapp崩溃的原因。 Realloc
返回没有错误,所以我猜它分配了足够的空间,我可以写入这个区域。 Valgrind
valgrind --leak-check=full --track-origins=yes --show-reachable=yes myapp
绝对没有无效的读/写。
是否有可能在这台特定的机器上内存本身已损坏并导致这些经常崩溃?或者我可能在myapp中的其他地方损坏了内存,但是如果是这种情况,那么为什么在写入无效写入时它不会更早崩溃?
提前感谢您的帮助。
装配件:
41c164: 00
41c165: 48 01 d0 add %rdx,%rax
41c168: 44 89 ea mov %r13d,%edx
41c16b: 0f ca bswap %edx
41c16d: 89 10 mov %edx,(%rax)
41c16f: 0f b6 94 24 47 10 00 movzbl 0x1047(%rsp),%edx
41c176: 00
我不确定这些信息是否相关,但所有机器,我的应用程序成功运行,都有英特尔处理器,导致问题的是AMD。
答案 0 :(得分:0)
这是我的问题的原因。
关键是在某个循环步骤stack->trcSize + size
超过UINT32_MAX。这意味着Realloc
实际上缩小了stc->trcData
。接下来,我定义buffer
,它现在远远落后于分配的区域。因此,当我写入缓冲区时,我会遇到段错误。
我检查过它确实是原因。