- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我最近在一个用GCC 8编译的软件中研究了段错误。代码如下所示(这只是一个草图)
struct Point
{
int64_t x, y;
};
struct Edge
{
// some other fields
// ...
Point p; // <- at offset `0xC0`
Edge(const Point &p) p(p) {}
};
Edge *create_edge(const Point &p)
{
void *raw_memory = my_custom_allocator(sizeof(Edge));
return new (raw_memory) Edge(p);
}
my_custom_allocator()
将指针返回未对齐的内存。代码崩溃是因为为了将原始点
p
复制到新对象的字段
Edge::p
中,编译器在[内联]构造函数代码中使用了
movdqu
/
movaps
对
movdqu 0x0(%rbp), %xmm1 ; read the original object at `rbp`
...
movaps %xmm1, 0xc0(%rbx) ; store it into the new `Edge` object at `rbx` - crash!
movaps
崩溃。我的错。
movaps
,就像在我的代码中一样。这
#include <new>
#include <cstdlib>
struct P { unsigned long long x, y; };
unsigned char buffer[sizeof(P) * 100];
void *alloc()
{
return buffer;
}
void foo(const P& s)
{
void *raw = alloc();
new (raw) P(s);
}
foo(P const&):
movdqu xmm0, XMMWORD PTR [rsi]
movaps XMMWORD PTR buffer[rip], xmm0
ret
movups
。例如。如果我在上面的示例中“隐藏”了分配器的定义,它将选择同一代码中的
movups
foo(P const&):
push rbx
mov rbx, rdi
call alloc()
movdqu xmm0, XMMWORD PTR [rbx]
movups XMMWORD PTR [rax], xmm0
pop rbx
ret
movaps
呢?就我而言,
my_custom_allocator()
的实现在调用时对于编译器是不可见的,这就是为什么我希望GCC选择
movups
的原因。
movups
,最好在任何地方使用?
最佳答案
更新:由于x86-64系统V上的alignof(Edge)
,long double
为16,因此在UB的未对齐地址处添加一个是UB。这告诉GCC使用movaps
是安全的。
IDK为什么从(%rbp)
加载它也没有使用movaps
。我以为隐含的Edge不会对齐16字节,因此基于该猜测(我将其移至最后),此答案的整个内容都是如此。
某些类型可能需要16字节对齐,尤其是long double
x86-64系统V上的 alignof(max_align_t) == 16
。替代malloc
至少需要返回对齐的内存,以分配16字节或更大的内存。
(当然,较小的分配不能容纳16个字节的对象,因此不需要16个字节的对齐方式。您可以要求对象的特定实例与alignas(16) int foo;
过度对齐,但是类型本身是否具有更高的对齐方式?对齐方式还具有较大的sizeof
,因此数组仍将遵守常规规则,并且每个元素都满足对齐要求。)
另请参见Why does unaligned access to mmap'ed memory sometimes segfault on AMD64?,其中带有未对齐的uint16_t*
的自动矢量化会导致段错误。同样,Pascal Cuoq's blog about alignment并具有比alignof(T)
少的对齐方式的对象也是未定义的行为,并且对于编译器来说,没有UB的假设如何深入。
指令选择
GCC和clang只要能证明必须充分对齐内存就使用movaps
。 (假设没有UB)。在Core2和更早版本以及K10和更早版本上,即使内存在运行时碰巧对齐,未对齐的存储指令也会变慢。
Nehalem和Bulldozer对此进行了更改,但即使只能在具有廉价movaps
的CPU上执行,GCC仍然使用-mtune=haswell
甚至使用vmovaps
,甚至使用-march=haswell
和vmovups
。
MSVC和ICC从不使用movaps
,这会损害非常旧的CPU上的性能,但有时会让您摆脱数据对齐问题。它们会将对齐后的负载折叠到SSE指令(如paddd xmm0, [rdi]
)(需要对齐,不同于AVX1等效文件)的SSE指令的内存操作数中,因此它们有时仍会生成会因对齐错误而出错的代码,但通常仅在启用优化的情况下。 IMO并不是特别好。alignof(Point)
只能为8(继承其最对齐的成员int64_t
的对齐方式)。因此,GCC只能证明任意Point
的8字节对齐,而不是16。
对于静态存储,GCC可以知道它选择将数组对齐16,因此可以使用movaps
/movdqa
从该数组加载。 (此外,x86-64 System V ABI要求将16字节或更大的静态数组与16对齐,因此,即使对于在其他某个编译单元中定义的extern unsigned char buffer[]
全局变量,GCC也可以假定这样做。)
您尚未显示Edge
的定义,因此IDK为什么它具有16字节对齐,但可能是alignof(Edge) == 16
?否则,可能是编译器错误。
但是它使用Edge
从堆栈中加载原始movups
对象的事实似乎表明alignof(Edge) < 16
raw_memory = __builtin_assume_aligned(raw_memory, 8);
可能有帮助吗? IDK是否可以告诉GCC假设比其他人认为的要低。
您可以告诉GCC,可以通过定义如下的typedef来使Edge
(或int
)始终未对齐:
typedef long __attribute__((aligned(1), may_alias)) unaligned_aliasing_long;
may_alias
实际上与对齐正交,但是值得一提,因为这种情况的用例之一是从
char[]
缓冲区中加载用于解析字节流。在这种情况下,您会两者都想要。这是使用
memcpy(tmp, src, sizeof(tmp));
进行未对齐的严格混叠安全加载的替代方法。
may_alias
定义__m128
,并使用may_alias,aligned(1)
作为定义_mm_loadu_ps
的一部分(未对齐的SIMD负载(如movups
)的内在函数)。 (不需要
may_alias
从
float
数组中加载float vector ,但是需要
may_alias
从其他内容中加载float。)
unsigned long
是安全的。 (必须在不使用
-flto
的情况下进行编译,因此它不能内联到其他glibc函数中,并且由于违反严格混叠而中断。)
alignof(Edge) < 16
编写。这里不是这种情况,即使不是问题的起因,函数属性也可能很有用,即使它们不是问题的起因。也可能不是可行的解决方法。)
__attribute__ ((assume_aligned (8)))
来告知GCC它返回的指针的对齐方式。
alignof(max_align_t) == 16
等原因,x86-64 System V上的
long double
,以及Windows x64上的
mmap
)。
malloc
并对其进行了特殊处理。但是,如果您的函数没有ISO C或C++定义的名称或GNU C属性,那将令人惊讶。 IDK,如果不是编译器错误,那么根据您所显示的内容,这是迄今为止最好的猜测。 (这是可能的。)
void*
mis-alignment Q&A:
void* my_alloc1 (size_t) __attribute__((assume_aligned (16)));
void* my_alloc2 (size_t) __attribute__((assume_aligned (32, 8)));declares that
my_alloc1
returns 16-byte aligned pointers and thatmy_alloc2
returns a pointer whose value modulo 32 is equal to 8.
movups
会比正在构造的对象的类型具有更多的对齐方式。
我们可以使用Edge
从某个地方加载alignof(Edge) < 16
。那似乎表明__attribute__((alloc_size(1)))
。
alloc_align (position)
进行指示,否则不要这样做。
关于c++ - GCC : how does it decide?中的`movaps`与`movups`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61196175/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!