64位Linux默认使用小内存模型,它将所有代码和静态数据置于2GB地址限制之下.这可确保您可以使用32位绝对地址.较旧版本的gcc使用静态数组的32位绝对地址,以便为相对地址计算保存额外的指令.但是,这不再有效.如果我尝试在汇编中创建一个32位的绝对地址,我会收到链接器错误:"在创建共享对象时,不能使用".data"重定位R_X86_64_32S;使用-fPIC重新编译".当然,此错误消息具有误导性,因为我没有创建共享对象,-fPIC也没有帮助.到目前为止我发现的是:gcc版本4.8.5对静态数组使用32位绝对地址,gcc版本6.3.0不使用.版本5可能也没有.binutils 2.24中的链接器允许32位绝对地址,而2.28则不允许.
这种变化的后果是必须重新编译旧库并破坏传统汇编代码.
现在我想问一下:这个改变是什么时候做的?它在某处记录了吗?是否有一个链接器选项,使其接受32位绝对地址?
不,这不是如何检测整数溢出的重复?.问题是一样的,但问题是不同的.
gcc编译器可以优化掉溢出检查(使用-O2),例如:
int a, b;
b = abs(a); // will overflow if a = 0x80000000
if (b < 0) printf("overflow"); // optimized away
Run Code Online (Sandbox Code Playgroud)
gcc人认为这不是一个错误.根据C标准,溢出是未定义的行为,它允许编译器执行任何操作.显然,任何事情都包括假设溢出永远不会发生.不幸的是,这允许编译器优化掉溢出检查.
最近的CERT文件中描述了检查溢出的安全方法.本文建议在添加两个整数之前执行类似的操作:
if ( ((si1^si2) | (((si1^(~(si1^si2) & INT_MIN)) + si2)^si2)) >= 0) {
/* handle error condition */
} else {
sum = si1 + si2;
}
Run Code Online (Sandbox Code Playgroud)
显然,当你想确保结果有效时,你必须在一系列计算中的每个+, - ,*,/和其他操作之前做这样的事情.例如,如果要确保数组索引不受限制.这太麻烦了,几乎没有人这样做.至少我从未见过一个系统地执行此操作的C/C++程序.
现在,这是一个根本问题:
在访问阵列之前检查数组索引很有用,但不可靠.
使用CERT方法检查一系列计算中的每个操作都是可靠但无用的.
结论:在C/C++中没有有用且可靠的方法来检查溢出!
我拒绝相信这是在编写标准时的意图.
我知道有一些命令行选项可以解决问题,但这并没有改变我们对标准或其当前解释存在根本问题的事实.
现在我的问题是:gcc的人服用的"未定义行为"的解释时,它允许他们优化掉溢出检查,否则过犹不及是C/C++标准坏了吗?
补充说明: 对不起,您可能误解了我的问题.我不是问如何解决这个问题 - 这已经在其他地方得到了回答.我在问一个关于C标准的更基本的问题.如果没有有用且可靠的检查溢出的方法,那么语言本身就是可疑的.例如,如果我使用边界检查创建一个安全的数组类,那么我应该是安全的,但是如果边界检查可以被优化掉,我就不会这样做.
如果标准允许这样做,则标准需要修订或标准需求修订的解释.
补充说明2: 这里的人似乎不愿意讨论"未定义行为"的可疑概念.C99标准列出了191种不同的未定义行为( …
我正在设计一个新的微处理器指令集(www.forwardcom.info),我想使用NAN传播来跟踪错误.但是,IEEE 754浮点标准中有许多奇怪的事情可以防止这种情况发生.
首先,我想使用NAN传播而不是错误捕获的原因是我有可变长度的向量寄存器.例如,如果我有一个带有8个元素的浮点向量,并且我在第一个元素中有1/0而在第六个元素中有0/0,那么我只得到一个陷阱,但如果我在计算机上运行相同的程序矢量长度的一半然后我得到两个陷阱:一个用于无穷大,一个用于NAN.我希望结果与向量长度无关,所以我需要依赖于NAN和INF的传播而不是陷阱.NAN和INF值将通过计算传播,以便在最终结果中检查它们.NAN表示包含一些称为有效负载的位,可用于有关错误源的信息.
但是,IEEE 754浮点标准中存在两个阻止NAN值可靠传播的问题.
第一个问题是具有不同有效载荷的两个NAN的组合只是两个值中的一个.例如,NAN1 + NAN2给出NAN1.这违反了a + b = b + a的基本原则.编译器可以交换操作数,以便在不同的编译器或不同的优化选项上获得不同的结果.我更喜欢得到两个有效载荷的按位OR组合.如果每个错误条件都有一位,那么这将起作用,但当然,如果有效负载包含更复杂的信息(例如具有动态类型的语言中的NAN装箱),则无效.标准委员会实际讨论了OR'ing解决方案(参见http://grouper.ieee.org/groups/754/email/msg01094.html).我不知道他们为什么拒绝这个提议.
第二个问题是如果只有一个输入是NAN,则min和max函数不传播NAN.换句话说,min(1,NAN)= 1.可靠的NAN传播当然需要min(1,NAN)= NAN.我不知道为什么标准会说这个.
在名为ForwardCom的新微处理器系统中,我想避免这些不幸的怪癖并指定NAN1 + NAN2 = NAN1 | NAN2和min(1,NAN)= NAN.
现在我的问题是:首先,我是否需要一个选项切换来在严格的IEEE一致性和可靠的NAN传播之间进行切换?引用标准:
安静的NaN应该由实施者自行决定提供从无效或不可用的数据和结果中继承的回顾性诊断信息.为了便于传播NaN中包含的诊断信息,应尽可能多地保留NaN操作结果中的信息.
注意标准在这里说"应该",在其他地方有"应该".这是否意味着我允许偏离建议?
第二个问题:我找不到任何实际使用NAN传播来跟踪错误的例子.也许这是因为标准的弱点.我想为不同的错误条件定义不同的有效负载位,例如:
0/0,0*∞,∞/∞,模(1,0),模(∞,1),∞-∞,以及涉及无穷大和除零的其他误差.
sqrt(-1),log(-1),pow(-1,0.1)以及从对数和幂导出的其他错误.
asin(2)和其他数学函数.
明确的分配.当变量初始化为NAN时,这可能很有用.
用户定义的错误代码有很多空位.
这是否已经完成,或者我是否必须从零开始创造一切?我有什么问题需要考虑(除了某些语言的NAN拳击)
我找不到任何 -fno-trapping-math 选项有效的示例。
我希望 -ftrapping-math 禁用可能影响是否生成陷阱的优化。例如,使用 x87 指令或 FMA 指令计算具有扩展精度的中间值可以防止发生溢出异常。-ftrapping-math 选项不会阻止这种情况。
公共子表达式消除可能会导致发生一个异常而不是两个异常,例如优化 1./x + 1./x = 2./x 在 x=0 时将生成一个陷阱而不是两个。-ftrapping-math 选项不会阻止这种情况。
请给出一些被 -fno-trapping-math 阻止的优化示例。
您能否推荐比 gcc 手册更好地解释不同浮点优化选项的任何文档,也许包含每个选项优化的代码的具体示例?可能适用于其他编译器。
x86 Clang 有一个我在 2013 年报告的错误。它得到了确认,但他们从未修复过。我该怎么做才能让他们修复它?
错误报告在这里:https : //bugs.llvm.org/show_bug.cgi?id=17164
描述:
__m128 x; // vector of four float
__m128i y; // vector of four int
x = y; // does not convert int to float but preserves the bits
Run Code Online (Sandbox Code Playgroud)
诸如 __m128、__m128i、__m128d 之类的内在向量类型会相互无声地进行位转换,从而产生奇怪的结果。所有其他编译器将这些向量类型视为不同的类型。没有任何选项可以使 Clang 与其他编译器的内在向量类型兼容。
这是 Vector 类库 ( https://www.agner.org/optimize/#vectorclass ) 的一个大问题。我不知道该怎么做才能让他们修复这个错误。请帮忙。
类Unix系统中的共享对象(*.so)由于符号插入而效率低下:.so内部对全局变量的每次访问都需要GOT查找,而.so内部从一个函数到另一个函数的每次调用都需要一个PLT抬头.因此,我很高兴看到gcc版本5.1添加了选项-fno-semantic-interposition.但是,当我尝试在没有使用PLT的情况下创建一个函数调用另一个函数的.so时,我收到错误消息:
在创建共享对象时,不能使用符号`functionname'重定位R_X86_64_PC32; 用-fPIC重新编译
我期望选项-fno-semantic-interposition可以消除此错误消息,但事实并非如此.-mcmodel = large也无济于事.对函数的引用确实与位置无关,错误消息实际确认了这一点(R_X86_64_PC32表示在64位模式下与PC相关的32位重定位).-fPIC实际上并不意味着与位置无关,正如名称所暗示的那样,它实际上意味着使用GOT和PLT.
我无法使用,__attribute__((visibility ("hidden")))
因为被调用的函数和调用者是在单独的文件中编译的(调用者在C++中,称为函数在汇编中).
我试图制作一个汇编列表来查看-fno-semantic-interposition选项的作用.我发现当一个函数在同一个文件中调用另一个函数时,它会引用一个本地别名,但在另一个文件中调用一个函数时它仍然使用PLT.
(g ++版本是5.2.1 Ubuntu,64位模式).
有没有办法让链接器在没有GOT/PLT查找的情况下接受.so内的交叉引用?
我正在研究并行处理算法以提高处理速度。\n我想测试Agner Fog\ 的矢量类库 VCL。
\n\n我想知道如何选择不同的向量类,例如Vec16c
(SSE2 指令集)和Vec32c
(AVX 指令集)。
我使用的是 Intel\xc2\xae Atom\xe2\x84\xa2 x5-Z8350 处理器,根据规格,它支持 SSE4.2 指令集。
\n\n如何在硬件支持方面有效选择向量类?\n对于我的处理器,我可以使用 AVX 指令集推荐的 Vec32c 吗?
\n