【问题标题】:Member value lost when passing object by pointer通过指针传递对象时成员值丢失
【发布时间】:2019-12-28 02:08:39
【问题描述】:

我对 FreeBSD 世界非常陌生,目前正在将我的终端仿真库从 Linux 移植到 FreeBSD 和 Mac OS。我遇到了一些非常奇怪的行为,比如当我通过指针传递一个结构到子例程时,成员值被清零。这不会在 Linux 或 Mac OS 上发生。编译器是 GCC 还是 Clang 也没关系。

在子例程被调用之前,我已经确认成员值是正确的,并且通过指针传递父结构。

我在 Linux 和 Mac OS 上测试了相同的代码,它们没有出现问题。

我在 FreeBSD 上在 GCC 和 Clang 之间切换,但似乎没有效果。

我认为堆栈粉碎可能会发生,但似乎不太可能,因为 ulimit 显示 Linux 上的堆栈大小为 8M,但在 FreeBSD 上它要大得多(524 MB)。我也尝试过使用 -fstack-protector-strong 进行编译,但这些都不重要。

#include "vterm.h" 
#include "vterm_private"  // vterm_t and vterm_desc_t defined here

void vterm_cursor_move_backward(vterm_t* vterm) {
  vterm_desc_t* v_desc = NULL;
  int min_row;
  int idx;

  // idx = vterm_buffer_get_active(vterm);
  idx = 0;  // hard set to 0 just for debugging
  v_desc = &vterm->vterm_desc[idx];

  // printf() will display a value of zero
  printf("%d\n\r", v_desc->ccol);
  fflush(stdout);
}

void vterm_interpret_ctrl_char(vterm_t* vterm, const char* data) {
  vterm_desc_t *v_desc = NULL;
  int idx;
  char verb;

  // idx = vterm_buffer_get_active(vterm);
  idx = 0;  // hard set to 0 just for debugging
  v_desc = &vterm->vterm_desc[idx];

  verb = data[0];

  switch (verb) {
    case '\b': {
      // the following printf will print a positive number
      printf("%d\n\r", v_desc->ccol);
      fflush(stdout);
      vterm_cursor_move_backward(vterm);
      break;
    }
  }
}

我希望 v_desc->ccol 的值在两个函数中是相同的。 Godbolt Link Github Link 查看文件 vterm_ctrl_char.c 和 vterm_cursor.c

【问题讨论】:

  • 你能给我们vterm_t的定义和/或源代码的链接吗?我想尝试编译您问题中的代码。
  • 您是否尝试过使用未定义行为 (UB) Sanitizer (-fsanitize=undefined) 或 Address Sanitizer (-fsanitize=address -fno-omit-frame-pointer) 编译和运行您的代码?
  • @cmwt,当然。项目位于:github.com/TragicWarrior/libvterm,分支为 freebsd-bugfixes-2 代码 sn-ps 来自文件 vterm_ctrl_char.c 和 vterm_cursor.c
  • @cmwt,我试过 -fsanitize=address 但我没有尝试过其他的。我现在就这样做。
  • @Bryan_Christ,但vterm_interpret_ctrl_char() 没有v_desc 的声明,只有vterm_cursor_move_backward() 有。

标签: c pointers stack freebsd


【解决方案1】:

经过无数小时的调试,我发现vterm_desc_t 结构中的数据实际上正在移动,导致成员值设置为零。虽然,ncurses 头文件是通过vterm_private.h 包含的,但在 FreeBSD 上这似乎并不重要。 GCC 和 Clang 都乐于以错误/不完整的对齐方式静默编译 vterm_cursor.c 翻译单元。

我建议任何遇到问题的人尝试单独编译每个翻译单元,这就是我发现它的方式。例如gcc -S vterm_cursor.c

感谢所有查看此内容的人。

【讨论】:

    猜你喜欢
    • 2013-06-28
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 1970-01-01
    • 2018-04-14
    相关资源
    最近更新 更多