- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在尝试用不同的方法对 Schoenhage 基数转换树的叶子进行编码时,我偶然发现了一个问题,即编译器(GCC、clang)用一个小常数乘以倒数来优化除法。正如他们应该的那样,没有提示。所以我决定添加一些内联汇编来获得可比较的基准,但我得到的是段错误。
代码(不是最小的例子,但一些上下文可能会有所帮助)
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define ARRAY_LENGTH 33
static const char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '+',
'/' };
static void to_radix_recursive(unsigned int a, unsigned int b,
char *result, int *index) {
unsigned int r = 0u, q = 0u;
int i;
char c;
if (a == 0u) {
return;
}
#ifdef CZ_USE_ASM
//printf("BEFORE a = %u, b = %u, q = %u, r = %u\n", a, b, q, r);
__asm__("xorl %%edx, %%edx;"
"movl %2, %%eax;"
"movl %3, %%ebx;"
"divl %%ebx;"
: "=a"(q), "=d"(r)
: "g"(a), "g"(b)
);
//printf("AFTER a = %u, b = %u, q = %u, r = %u\n\n", a, b, q, r);
#else
q = a / b;
r = a % b;
#endif
to_radix_recursive(q, b, result, index);
c = digits[r];
i = *index; /* Line 41 */
result[i] = c;
(*index)++;
}
int main(void) {
int idx;
unsigned int a, b;
char result[ARRAY_LENGTH] = {'\0'};
/* All checks and balances ommitted! */
/* 0 < a <= UINT_MAX */
a = 1234567;
#ifdef CZ_USE_CONSTANT
/* Most compilers optimimize to multiplication with reciprocal here */
b = 10;
#else
/* Should press the optimizer to use "divl" */
for (b = 2u; b < 64u; b++) {
idx = 0;
to_radix_recursive(a, b, result, &idx);
printf("Result recursive = %s for radix %u\n", result,b);
for (int i = 0; i < ARRAY_LENGTH; i++) {
result[i] = '\0';
}
}
#endif
exit(EXIT_SUCCESS);
}
-DCZ_USE_ASM
的预期输出
Result recursive = 100101101011010000111 for radix 2
Result recursive = 2022201111201 for radix 3
Result recursive = 10231122013 for radix 4
Result recursive = 304001232 for radix 5
Result recursive = 42243331 for radix 6
Result recursive = 13331215 for radix 7
Result recursive = 4553207 for radix 8
Result recursive = 2281451 for radix 9
Result recursive = 1234567 for radix 10
Result recursive = 773604 for radix 11
Result recursive = 4B6547 for radix 12
Result recursive = 342C19 for radix 13
Result recursive = 241CB5 for radix 14
Result recursive = 195BE7 for radix 15
Result recursive = 12D687 for radix 16
Result recursive = ED4EA for radix 17
Result recursive = BDC71 for radix 18
Result recursive = 98IG4 for radix 19
Result recursive = 7E687 for radix 20
Result recursive = 6769J for radix 21
Result recursive = 55KGF for radix 22
Result recursive = 49AHJ for radix 23
Result recursive = 3H787 for radix 24
Result recursive = 3407H for radix 25
Result recursive = 2I679 for radix 26
Result recursive = 28JDJ for radix 27
Result recursive = 206JJ for radix 28
Result recursive = 1LHS8 for radix 29
Result recursive = 1FLM7 for radix 30
Result recursive = 1ADKN for radix 31
Result recursive = 15LK7 for radix 32
Result recursive = 11BM4 for radix 33
Result recursive = VDWR for radix 34
Result recursive = SRSC for radix 35
Result recursive = QGLJ for radix 36
Result recursive = ODTP for radix 37
Result recursive = MIaN for radix 38
Result recursive = KVQM for radix 39
Result recursive = JBO7 for radix 40
Result recursive = HbHG for radix 41
Result recursive = GRaJ for radix 42
Result recursive = FMTb for radix 43
Result recursive = ELUF for radix 44
Result recursive = DOTb for radix 45
Result recursive = CVKJ for radix 46
Result recursive = BffI for radix 47
Result recursive = B7e7 for radix 48
Result recursive = AO9C for radix 49
Result recursive = 9hfH for radix 50
Result recursive = 9FXA for radix 51
Result recursive = 8eTZ for radix 52
Result recursive = 8FQc for radix 53
Result recursive = 7jKJ for radix 54
Result recursive = 7N6b for radix 55
Result recursive = 71bl for radix 56
Result recursive = 6bu4 for radix 57
Result recursive = 6Ivb for radix 58
Result recursive = 60cp for radix 59
Result recursive = 5gu7 for radix 60
Result recursive = 5Qln for radix 61
Result recursive = 5BAN for radix 62
Result recursive = 4x3J for radix 63
但如上所述:它改为段错误。我把代码拉开一点,每行一个操作,然后运行
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./divmod
打印
==9546== Memcheck, a memory error detector
==9546== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9546== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9546== Command: ./divmod
==9546==
==9546== Invalid read of size 4
==9546== at 0x4005FA: to_radix_recursive (divmod.c:41)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== Address 0x2 is not stack'd, malloc'd or (recently) free'd
==9546==
==9546==
==9546== Process terminating with default action of signal 11 (SIGSEGV)
==9546== Access not within mapped region at address 0x2
==9546== at 0x4005FA: to_radix_recursive (divmod.c:41)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== by 0x4005F1: to_radix_recursive (divmod.c:39)
==9546== If you believe this happened as a result of a stack
==9546== overflow in your program's main thread (unlikely but
==9546== possible), you can try to increase the size of the
==9546== main thread stack using the --main-stacksize= flag.
==9546== The main thread stack size used in this run was 8388608.
==9546==
==9546== HEAP SUMMARY:
==9546== in use at exit: 0 bytes in 0 blocks
==9546== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==9546==
==9546== All heap blocks were freed -- no leaks are possible
地址
0x2
非常低,提示取消引用失败的指针,确实如此。
printf
的两次调用的原因您可能已经猜到了:如果您使用一个(我昨天需要同时使用两个),它就可以工作。这几乎总是由某处的某些 UB(未定义行为)引起的。
最佳答案
问题是在您的内联汇编中,您执行以下操作:
__asm__("xorl %%edx, %%edx;"
"movl %2, %%eax;"
"movl %3, %%ebx;"
"divl %%ebx;"
: "=a"(q), "=d"(r)
: "g"(a), "g"(b)
);
GCC/CLANG 是非常无情的。如果你修改一个寄存器,你需要告诉编译器它将被修改。在这个内联汇编代码中,您已经说过 EAX 和 EDX 只是输出寄存器(它们将被修改),但您没有告诉编译器您修改/破坏了 EBX。一个简单的解决方法是将 EBX 添加到 clobber 列表中,如下所示:
__asm__("xorl %%edx, %%edx;"
"movl %2, %%eax;"
"movl %3, %%ebx;"
"divl %%ebx;"
: "=a"(q), "=d"(r)
: "g"(a), "g"(b)
: "ebx"
);
现在编译器不会假设 EBX 仍然包含与运行内联汇编代码之前相同的值。
MOV
开头说明您可能采取了错误的方法,因为不使用内联汇编操作数(和约束)本身来允许编译器尝试生成最有效的代码版本。您的内联程序集可能如下所示:
__asm__("divl %4"
: "=a"(q), "=d"(r)
: "a"(a), "d"(0), "r"(b)
);
我们创建第 5 个操作数以在编译器选择的寄存器中传递除数。我们还在操作数中将 EDX 设置为零,而不是在内联汇编中设置。此版本还为输入和输出操作数重用 EAX 和 EDX 寄存器,需要使用的寄存器更少。
关于c - 内联汇编后指针取消引用 (SIGSEGV) 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64265487/
我在使用以下代码时遇到问题: function http_file_exists($url){ $f=fopen($url,"r"); if($f){ fclose($f); retu
我已经通过 Git 部署到 Azure 几个月了,没有出现重大问题,但现在我似乎遇到了一个无法克服的错误。 我创建了一个新的 Azure 网站,为正在开发的项目创建单独的预览链接。我在新站点上设置了
我已经通过flutter创建了一个App并完成了它,我想在flutter文档中阅读时进行部署。 我收到此错误: FAILURE: Build failed with an exception. * W
我在Windows 10中使用一些简单的Powershell代码遇到了这个奇怪的问题,我认为这可能是我做错了,但我不是Powershell的天才。 我有这个: $ix = [System.Net.Dn
我正在尝试使用 RapidJSON 解析从服务器接收到的数据。以下是收到的确切字符串: [ { "Node": "9478149a08f9", "Address": "172.17
我尝试为 ios 编译 OpenCV。我总是收到这些错误。我用不同版本的opencv试了一下,结果都是一样的。 我运行这个:python 平台/ios/build_framework.py ios_o
我在一台机器上做基本的发布/订阅,我的客户端是 StackExchange-Redis 的 C# 客户端,我在同一台机器上运行基于 Windows 的 Redis 服务器(服务器版本 2.8.4) 当
我有这段代码,但无法执行,请帮我解决这个问题 连接 connect_error) { die ("connection failed: " . $terhubung->connect_erro
我在 tomcat 上运行并由 maven 编译的 Web 应用程序给出了以下警告和错误。我可以在本地存储库中看到所有 JAR,但有人可以帮忙吗。 WARNING: Failed to scan JA
我正在 Windows 8 上使用 Android Studio 开发一个 android 应用程序,我正在使用一些 native 代码。突然间我无法编译我的 C 文件。当我运行 ndk-build
下面的代码对类和结构的成员进行序列化和反序列化。序列化工作正常,但我在尝试使用 oarch >> BOOST_SERIALIZATION_NVP(outObj); 反序列化时遇到了以下错误; 代码中是
如果我运行此命令“rspec ./spec/requests/api/v1/password_reset_request_spec.rb”,此文件中的所有测试都会通过。 但是,当我运行“rspec”时
我在尝试执行测试以使用 Protractor 上传文件时出错,我的代码是这个 it('it should be possible to upload a file', function() {
System.loadLibrary("nativefaceswap"); 当我运行我的应用程序时,我在 Android Studio 中发现了此类错误。在logcat中显示: java.lang.U
我希望有人能帮助我!使用任何方法或命令行的任何 SSL/HTTPS 调用均无效。 我在 Windows 10 中使用 Ubuntu Server 18.04 作为子系统。我的问题是昨天才开始出现的,因
通过删除这两个值将日期字段从 null=True 和 Blank=True 更改为 required 时,使用 db.alter 命令时遇到问题。 当以下行被注释掉时,迁移运行不会出现问题。
我第一次使用 Heroku 尝试创建应用程序(使用 SendGrid 的 Inbound Parse Webhook"和 Twilio SMS 通过电子邮件发送和接收 SMS 消息)。通过 Virtu
我正在将我的 swift 项目更新到 Xcode 7 上的 Swift 2.0。xcode 在构建项目时报告了以下错误: 命令/Applications/Xcode.app/Contents/Deve
在我的代码中,SSL 库函数 SSL_library_init() 没有按预期返回 1。我如何才能看到它返回了什么错误? 我在 SSL_library_init() 之后调用了 SSL_load_er
我正在尝试运行在以下链接中找到的答案: Asynchronously Load the Contents of a Div 但是当我这样做时,我会遇到我不太理解的错误。 我的代码: $(documen
我是一名优秀的程序员,十分优秀!