Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 编译器过度优化导致数据运行时和调试不一致_C - Fatal编程技术网

C 编译器过度优化导致数据运行时和调试不一致

C 编译器过度优化导致数据运行时和调试不一致,c,C,我有以下代码: struct cre_eqEntry * cre_eventGet(struct cre_eqObj *eq_obj) { struct cre_eqEntry *eqe = cre_queueTailNode(&eq_obj->q); Memcpy(&tmpEqo, eq_obj, sizeof(struct cre_eqObj)); volatile u32 ddd = 0; ddd = ((struct cre_e

我有以下代码:

struct cre_eqEntry *      
cre_eventGet(struct cre_eqObj *eq_obj)
{
   struct cre_eqEntry *eqe = cre_queueTailNode(&eq_obj->q);
   Memcpy(&tmpEqo, eq_obj, sizeof(struct cre_eqObj)); 
   volatile u32 ddd = 0;
   ddd = ((struct cre_eqEntry *)(eq_obj->q.dma_mem.virtaddr + 4 * eq_obj->q.tail))->evt;
   CPUMemFenceReadWrite();    

   if (!ddd) {
      tmp = eq_obj->q.tail;                                                                                                                                                                                 
      assert(0);
      return NULL;
   }   
}
这是一段内核代码。当我运行它时,它在assert0失败。显然ddd应该是0。但当我使用GDB调试核心转储并打印出“struct cre_eqEntry*eq_obj->q.dma_mem.virtaddr+4*eq_obj->q.tail->evt”时,令人惊讶的是,该值不是0

所以我开始怀疑这是编译器过度优化的问题。以下是反汇编代码:

00000000000047ec <cre_eventGet>:
    47ec:       55                      push   %rbp
    47ed:       48 89 fe                mov    %rdi,%rsi
    47f0:       ba 80 00 00 00          mov    $0x80,%edx
    47f5:       53                      push   %rbx
    47f6:       48 89 fb                mov    %rdi,%rbx
    47f9:       48 83 ec 18             sub    $0x18,%rsp
    47fd:       0f b7 6f 24             movzwl 0x24(%rdi),%ebp
    4801:       0f b7 47 28             movzwl 0x28(%rdi),%eax
    4805:       0f af e8                imul   %eax,%ebp
    4808:       48 63 ed                movslq %ebp,%rbp
    480b:       48 03 6f 18             add    0x18(%rdi),%rbp
    480f:       48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # 4816 <cre_eventGet+0x2a>
    4816:       e8 00 00 00 00          callq  481b <cre_eventGet+0x2f>
    481b:       0f b7 43 28             movzwl 0x28(%rbx),%eax
    481f:       48 8b 53 18             mov    0x18(%rbx),%rdx
    4823:       c7 44 24 0c 00 00 00    movl   $0x0,0xc(%rsp)
    482a:       00 
    482b:       c1 e0 02                shl    $0x2,%eax
    482e:       48 98                   cltq   
    4830:       8b 04 02                mov    (%rdx,%rax,1),%eax
    4833:       89 44 24 0c             mov    %eax,0xc(%rsp)
    4837:       0f ae f0                mfence 
    483a:       8b 44 24 0c             mov    0xc(%rsp),%eax
    483e:       85 c0                   test   %eax,%eax
    4840:       74 14                   je     4856 <cre_eventGet+0x6a>
就我所见,汇编代码与C代码做了相同的事情

所以现在我想不出是什么导致了“ddd”不一致的问题

请给我一些提示

ddd=struct cre\u eqEntry*eq\u obj->q.dma\u mem.virtaddr+4*eq\u obj->q.tail->evt

简化代码。执行地址/边界检查/验证。您的问题可能是您正在取消引用进程/线程地址空间中的一些随机、未初始化的地址。

ddd=struct cre\u eqEntry*eq\u obj->q.dma\u mem.virtaddr+4*eq\u obj->q.tail->evt;可能违反了严格的别名规则,在没有看到整个代码的情况下,不能说100%确定

如果使用gcc/clang,请使用-fno严格别名编译,除非您希望重写代码以符合标准

对于后者,memcpyu32*&ddd,&struct cre_eqEntry*eq_obj->q.dma_mem.virtaddr+4*eq_obj->q.tail->evt,ddd的大小;但我猜您的代码库在许多地方可能有类似的违规行为,因此作为第一步,使用编译器标志将是一种查看这是否真的是问题的方法


神奇数字4也是可疑的,请检查您的代码,以检查这是否真的是正确的偏移量,并检查它是否超出分配的内存范围。

当然,只有在未定义NDEBUG的情况下,此assert调用才会生成错误消息。如果有,就执行!ddd。这不意味着ddd应该是非零的吗?或者我遗漏了什么?是另一个核心还是一个设备修改了ptr->evt?你有没有试过在gdb中运行它,并在cre_Event上设置一个断点来查看一步一步发生了什么?这是你的吗?如果是这样,它似乎并不完整;请阅读我刚刚链接到的页面。确保你的代码是最小的,目前这不是一个问题;你的代码是如此之小,以至于它还没有编译,可编译这是你目前的问题,可验证我们无法验证任何东西,因为我们无法编译。一旦你提供了这样一个例子,我想你会发现问题几乎肯定不是过度优化;你很可能把我们的注意力从真正的问题上移开了。我相信volatile在这里没有效果。如果内存围栏实际上是围栏,那么它是冗余的;如果围栏没有围栏,那么它实际上也没有帮助。