我正在处理一个奇怪的案例,我(突然)开始在库代码中开始出现分段错误(我刚才写过)。
该库有一个代码,负责复制缓冲区,这里是代码快照:
memory_manager_types::translation_status_t memory_manager::setMem(const uint64_t i_la, const void * const src_buff, const uint32_t i_size)
{
...
char* dst_ptr = reinterpret_cast<char*>(pa); // pa is a 'uint64_t' which holds the destination address
const char* src_ptr = static_cast<const char*>(src_buff);
std::copy(src_ptr, src_ptr + i_size, dst_ptr);
现在当我得到分段错误时,在回溯中我看到std::copy
调用了其他STL方法,这些方法最终来到__builtin_memmove
,而__memmove_ssse3()
又被编译器替换为src_buff
}。
这里的问题是这个特定情况下的-mpreferred-stack-boundary=4 -mstackrealign
值是0xXXXXXXXXX 509 ,根据我在this SO answer中看到的,SSSE3指令需要一些最小的对齐参数。该答案中的建议是尝试使用__memmove_ssse3()
标志编译代码,这样可以解决我的问题(或者只是掩盖它?)。
现在,如果初始假设是正确的,并且此处的问题是参数的对齐,那么为什么当发送到std::copy
的参数属于类型时,编译器会使用char *
可以应用无对齐假设的g++
?!
使用以下编译标志使用-m64 -fPIC -fmessage-length=0 -std=c++11 -O0 -g3
版本5.2.0完成原始编译:
-mpreferred-stack-boundary=4 -mstackrealign
并在添加其他
之后-mstackrealign
一切顺利通过。
EDIT1
我没有提到的并且可能是我的问题的答案是,使用我的库的代码是使用较低版本的GCC(4.2.2)编译的。
现在根据 const char* text = "hi";
printf("%s\n",text);
printf("%p\n", &text);
printf("%p\n", text);
标志的描述:
-mstackrealign
在入口处重新对齐堆栈。在Intel x86上,-mstackrealign选项将生成备用序言和结尾,以便在必要时重新调整运行时堆栈。这支持混合 遗留代码,保持4字节对齐堆栈与现代代码 保持一个16字节的堆栈以实现SSE兼容性。另请参见属性 force_align_arg_pointer,适用于个别职能。
默认情况下,G ++ 5.2.0是否假设16字节堆栈对齐?