【问题标题】:Array size - Segmentation fault - C数组大小 - 分段错误 - C
【发布时间】:2013-06-11 13:38:21
【问题描述】:

下面你看到一个代码sn-p:

int foo[262144]  __attribute__ ((aligned (8192)));

void
test49()
{
    __asm__("movl $0x0, %ecx");
    __asm__("movl %0,%%eax"::"r"(&foo));

#ifdef FOREVER
    while(1)
    {
#else
    for(int i=0; i < iters; i++)
    {
#endif
        __asm__("test_begin: addl $0x1,%ecx;");
        __asm__("mov 0x00(%eax),%ebx;\

我遇到了一个分段错误。

    __asm__("mov 0x00(%eax),%ebx;\

如果我将数组大小从256KB 更改为7MB6MB;我没有收到任何错误。不会是我没有空间吧?

我试图检查转储。它没有给我太多线索。

在这里

./microbenchmark 49
Performing Test49
[1]    12011 segmentation fault (core dumped)  ./microbenchmark 49

这是回溯。

gdb microbenchmark core
GNU gdb (GDB) SUSE (7.5.1-2.1.1)
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-suse-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /MB/test-l2-256/test-hit/microbenchmark...done.
[New LWP 12011]
Missing separate debuginfo for /lib/libc.so.6
Try: zypper install -C "debuginfo(build-id)=7e0834d74d3e93c3210d2405cde86dc995fe476c"
Missing separate debuginfo for /lib/ld-linux.so.2
Try: zypper install -C "debuginfo(build-id)=6a687db0baedc0db516006a7eedaee8f57f955c8"
Core was generated by `./microbenchmark 49'.
Program terminated with signal 11, Segmentation fault.
#0  0x08048603 in test49 () at microbenchmark.c:77
77              __asm__("mov (%eax),%ebx;\
(gdb) bt
#0  0x08048603 in test49 () at microbenchmark.c:77
#1  0x08048538 in main (argc=2, argv=0xfff68fb4) at microbenchmark.c:33

知道可能是什么问题吗?

谢谢。

【问题讨论】:

  • "不会是我没有空间吧?" - 这正是问题所在。堆栈不是很大,很容易 owevrflow。让你的数组static 怎么样(考虑到它的所有副作用)?
  • 源被截断,但除此之外,您不能保证存储在寄存器中的值将保留 __asm__ 块之间。 gcc 不对指令执行任何分析——它只知道输入、输出和破坏。例如,%eax%ecx 可能用作循环变量。
  • @H2CO3:这是一种解决方案。我需要先研究静态数组!
  • @BrettHale:那么您是否建议另一种方法来填充缓存行?
  • 我建议您逐步完成循环的几次迭代,看看寄存器是否反映了您期望的值。此外,请查看编译器为此函数生成的程序集。 %ebx 也用于 i386-ELF ABI 中的 PIC - 但这是以后的问题。

标签: c assembly segmentation-fault


【解决方案1】:

内联汇编很危险。你应该注意这些事情:

  1. 让 gcc 知道你在搞什么。例如,您正在更改 ecx,而 gcc 可能会假设 ecx 具有某些价值。你是内联程序集的“clobber”部分(例如__asm__("movl $0x0, %ecx":::"ecx")

  2. 不要假设寄存器不会在内联装配线之间发生变化。即使中间没有 C 行,gcc 也可以在那里插入汇编代码。使用带有多个汇编命令的单个内联汇编块。

  3. 如果您需要在汇编块之间传递数据,请使用 C 变量来完成。您可以将其定义为register 以使其更快。你甚至可以在 gcc 中选择你想要的寄存器(我忘了确切的语法)。

【讨论】:

  • @user2015933,您的代码示例 - 您在 ecx 中输入一个值,然后进入循环,然后查看 ecx。也许循环控制代码修改了ecx?
  • ecx 确实有一个值 - 0x00。每次迭代都会添加 16 个。
  • 我不知道 gcc 使用哪些寄存器进行循环控制。肯定会用到一些寄存器,也许不是 ecx,但这取决于编译器版本和标志。
  • 感谢您提供的有用提示。对问题的任何见解将不胜感激。
  • 据我所知,不遵循这些准则是问题的原因。
猜你喜欢
  • 2022-01-08
相关资源
最近更新 更多