繁体   English   中英

已跳过 function 本地 static object 的构造函数调用

[英]Constructor call of function local static object skipped

我写了以下 function:

inline void putc(int c)
{
  static Cons_serial serial;

  if (serial.enabled())
    serial.putc(c);
}

其中Cons_serial是 class 具有非平凡的默认构造函数。 我相信确切的 class 定义在这里并不重要,但你可以纠正我。 我正在使用以下标志为 x86 32 位和g++进行编译: -m32 -fno-PIC -ffreestanding -fno-rtti -fno-exceptions -fno-threadsafe-statics -O0 ,生成的putc汇编代码如下所示:

00100221 <_Z4putci>:
  100221:       55                      push   %ebp
  100222:       89 e5                   mov    %esp,%ebp
  100224:       83 ec 08                sub    $0x8,%esp
  100227:       b8 f8 02 10 00          mov    $0x1002f8,%eax
  10022c:       0f b6 00                movzbl (%eax),%eax
  10022f:       84 c0                   test   %al,%al
  100231:       75 18                   jne    10024b <_Z4putci+0x2a>
  100233:       83 ec 0c                sub    $0xc,%esp
  100236:       68 f0 02 10 00          push   $0x1002f0
  10023b:       e8 36 fe ff ff          call   100076 <_ZN11Cons_serialC1Ev>
  100240:       83 c4 10                add    $0x10,%esp
  100243:       b8 f8 02 10 00          mov    $0x1002f8,%eax
  100248:       c6 00 01                movb   $0x1,(%eax)
  10024b:       83 ec 0c                sub    $0xc,%esp
  10024e:       68 f0 02 10 00          push   $0x1002f0
  100253:       e8 4c fe ff ff          call   1000a4 <_ZNK11Cons_serial7enabledEv>
  100258:       83 c4 10                add    $0x10,%esp
  10025b:       84 c0                   test   %al,%al
  10025d:       74 13                   je     100272 <_Z4putci+0x51>
  10025f:       83 ec 08                sub    $0x8,%esp
  100262:       ff 75 08                pushl  0x8(%ebp)
  100265:       68 f0 02 10 00          push   $0x1002f0
  10026a:       e8 41 fe ff ff          call   1000b0 <_ZN11Cons_serial4putcEi>
  10026f:       83 c4 10                add    $0x10,%esp
  100272:       90                      nop
  100273:       c9                      leave  
  100274:       c3                      ret   

在执行期间,在100231第一次运行时会在 100231 处跳转,因此不会调用Cons_serial 为什么 x86 组件的知识值得怀疑,导致该组件的指令实际上是做什么的? 我假设代码旨在跳过后续 function 调用的构造函数调用。 但是为什么它在 function 第一次运行时也被跳过了呢?

编辑:此代码是我正在编写的 kernel 的一部分,我怀疑根本原因可能是我的内核的.bss 部分存在问题,这是我使用的 linker 脚本:

OUTPUT_FORMAT("elf32-i386")

ENTRY(_start)

SECTIONS
{
  . = 0x100000;
  .text : AT(0x100000) {
    *(.text)
  }

  .data : SUBALIGN(2) {
    *(.data);
    *(.rodata*);
  }

  .bss : SUBALIGN(4) {
    __bss_start = .;
    *(.COMMON);
    *(.bss*)
    . = ALIGN(4);
    __bss_end = .;
  }

  /DISCARD/ : {
    *(.eh_frame)
    *(.comment)
  }
}

这是我用来将 .bss 部分归零的代码:

extern uint32_t __bss_start;
extern uint32_t __bss_end;

void zero_bss()
{
  for (uint32_t bss_addr = __bss_start; bss_addr < __bss_end; ++bss_addr)
    *reinterpret_cast<uint8_t *>(bss_addr) = 0x00;
}

但是当zero_bss运行时, __bss_start0x27并且__bss_end0x101 ,这根本不是我想要的(BSS 毕竟应该包含地址0x1002f8 )。

我现在已经解决了,来自@user3124812 的提示是让我到达那里的原因,再次感谢。 我的zero_bss代码有问题,我需要从 linker 脚本中获取__bss*标记的地址,即:

extern uint8_t __bss_start;
extern uint8_t __bss_end;

void zero_bss()
{
  uint8_t *bss_start = reinterpret_cast<uint8_t *>(&__bss_start);
  uint8_t *bss_end = reinterpret_cast<uint8_t *>(&__bss_end);

  for (uint8_t *bss_addr = bss_start; bss_addr < bss_end; ++bss_addr)
    *bss_addr = 0x00;
}

现在一切正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM