使用带有自定义对齐分配器实现的最新 g++ 使用 SSE 和 -O3 选项编译时出现非法指令(核心转储)
Posted
技术标签:
【中文标题】使用带有自定义对齐分配器实现的最新 g++ 使用 SSE 和 -O3 选项编译时出现非法指令(核心转储)【英文标题】:Illegal instruction (core dumped) upon compiling with SSE and -O3 options using latest g++ with a custom alignment allocator implementation 【发布时间】:2014-11-13 06:51:20 【问题描述】:使用 g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7) 编译以下代码时使用编译命令“g++ -g -fno-omit-frame-pointer -msse2 -mssse3 - O3 Memory.cpp”,可执行文件在执行时引发“非法指令(核心转储)”。
它使用相同的编译器标志使用旧的 g++ 版本编译和运行没有问题。当编译器标志“-mssse3 -O3”被删除或替换为较低的优化级别(例如“-O2”)时,它也可以毫无问题地编译和运行。
如果同时使用旧的和新的 g++ 编译器,具有编译器标志“-msse2 -mssse3 -O3”,并且具有可移植的对齐内存分配器是必需的,存在哪些选项?以下代码中是否存在可以轻松修复的简单错误?最后,为什么会出现这个错误?
使用 gdb 时,触发此错误的行是:“memory[i] = (unsigned char)i;”。
非常感谢。
#include <iostream>
using std::cerr;
using std::cout;
using std::endl;
using std::flush;
#include <stdlib.h>
void *aligned_alloc(int alignment, int size)
const int pointer_size = sizeof(unsigned char *);
const int requested_size = size + alignment - 1 + pointer_size;
unsigned char *base = (unsigned char *)malloc(requested_size);
if (base == NULL) return NULL;
unsigned char *start = base + pointer_size;
const int trim_offset = (int)(((unsigned long long)(start+alignment-1)) & (alignment-1));
unsigned char *aligned = start + alignment - 1 - trim_offset;
*(unsigned char **)(aligned-pointer_size) = base;
return aligned;
void aligned_free(void **aligned)
if (*aligned == NULL) return;
unsigned char *base = *(unsigned char **)((unsigned char *)(*aligned) - sizeof(unsigned char *));
free(base);
*aligned = NULL;
int main()
unsigned char *memory = (unsigned char *)aligned_alloc(16, 120);
if (memory == NULL)
cout<<"ERROR: Unable to allocate memory."<<endl;
exit(1);
for (int i=0; i<120; i++)
memory[i] = (unsigned char)i;
aligned_free((void **)&memory);
return 0;
【问题讨论】:
aligned_alloc
是最新版本的 glibc 中的标准函数 - 我想知道您是否正在链接它而不是您自己的函数,或者类似的东西 - 也许尝试将您的函数重命名为my_aligned_alloc
/my_aligned_free
只是作为测试?
你用的是什么CPU?在 GDB 中,什么指令(不是行)以及在哪里导致陷阱(尝试(gdb) bt
、(gdb) disas
)?那时 insn 使用的寄存器的值是多少?此外,您可以通过将aligned
转换为unsigned char**
并将base
访问为unsigned char* base = ((unsigned char**)aligned)[-1];
来对您的ptr 算法进行一些deuglify
@PaulR 我也这么认为,但转念一想我打了折扣,因为至少在我的机器上aligned_alloc
没有被破坏,它的参数是size_t
,而这里我们谈论的是 C++ 和参数int
类型。尽管如此,还是值得一试重命名。
你用的是什么CPU?
哇。我从来没有想过我仍然会遇到不支持 SSSE3 指令集的 Intel CPU。我做了一个 cat /proc/cpuinfo ,它清楚地报告该标志丢失。为了完整起见,我在比较 1) 编译器 = "g++ (GCC) 4.4.4 20100630 (Red Hat 4.4.4-10)" on CPU = "Intel(R) Core(TM) i3-4010U CPU @ 1.70GHz" vs 2) 编译器 = "g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7)" on CPU = "Intel(R) Pentium(R) 4 CPU 3.00GHz"。我的印象是,我的代码肯定是罪魁祸首,而不是编译器。我想它也可能是硬件!谢谢!
【参考方案1】:
这是由不支持 SSSE3(Supplemental Streaming SIMD Extensions 3)指令子集(特别是某种 3GHZ P4)的 CPU 试图运行为支持该指令子集的 CPU 编译的代码引起的;只需从 GCC 命令行中删除 -mssse3
标志就足以使违规指令消失。
【讨论】:
以上是关于使用带有自定义对齐分配器实现的最新 g++ 使用 SSE 和 -O3 选项编译时出现非法指令(核心转储)的主要内容,如果未能解决你的问题,请参考以下文章
如何将最新数据附加到android中的自定义基本适配器列表视图?
使用自定义适配器实现 Expandable ListView
带有由 LoaderManager 管理的自定义适配器的 AlphabetIndexer
深度剖析结构体@自定义类型1---结构体的声明,自引用,变量定义和初始化 + 结构体内存对齐 + 结构体传参 + 结构体实现位段