C 为什么这个if段编译成无限循环?

C 为什么这个if段编译成无限循环?,c,assembly,arm,C,Assembly,Arm,C代码如下: s32 load_string(char* string_new, char const* string_orign) { StrEntry *entry = search_str_entry(string_orign); u8 buff_b[32]; u16 buff_u[32]; s32 read_size = 0; void *str_file = 0; if (entry !=

C代码如下:

s32 load_string(char* string_new, char const* string_orign)
{
    StrEntry *entry = search_str_entry(string_orign);
    u8        buff_b[32];
    u16       buff_u[32];
    s32       read_size = 0;
    void     *str_file = 0;

    if (entry != 0){
        cmemclr(buff_b, 32);
        cmemclr(buff_u, 64);
        sprintf(&buff_b[0], "c:/data/%03d.str", entry->fid);
        c2w(&buff_u[0], &buff_b[0], 32);
        if (TryOpenFile(&str_file, buff_u, OPEN_MODE_READ) == 0){
            cmemclr(string_new, 256);
            TryReadFile(&read_size, str_file, entry->offset, string_new, entry->size);

            CloseFile(str_file);
            return (s32)entry->size;
        }
    }
    return 0;
}
此函数的分解:

  003464ac <load_string>:
  3464ac:   e92d4010    push    {r4, lr}
  3464b0:   e1a00001    mov r0, r1
  3464b4:   ebffffda    bl  346424 <search_str_entry>
  3464b8:   e3500000    cmp r0, #0
  3464bc:   08bd8010    popeq   {r4, pc}
  3464c0:   eafffffe    b   3464c0 <load_string+0x14>
static inline void cmemclr(void *buf, u32 size)
{
    u8 *dst = (u8*)buf;

    while(--size >= 0){
        dst[size] = 0;
    }
}
cmemclr有缺陷。根据对问题的编辑,cmemclr是:

由于size的类型为u32,可能是无符号的,-size>=0始终为真。代码进入无限循环

编辑问题前的回答 一种可能是您显示的汇编代码不完整,当前显示为b 3464c0的代码稍后将解析为另一个地址

假设程序集是正确的,并且不是等待进一步链接解析的不完整占位符,编译器已将if语句中的代码优化为无限循环,这可能是因为语句中存在未定义的行为,因此无限循环是允许的行为,也可能是因为语句中的某些内容执行无限循环

由于您尚未提供if语句中使用的例程或宏的实现或规范,因此无法进行进一步诊断。

cmemclr有缺陷。根据对问题的编辑,cmemclr是:

由于size的类型为u32,可能是无符号的,-size>=0始终为真。代码进入无限循环

编辑问题前的回答 一种可能是您显示的汇编代码不完整,当前显示为b 3464c0的代码稍后将解析为另一个地址

假设程序集是正确的,并且不是等待进一步链接解析的不完整占位符,编译器已将if语句中的代码优化为无限循环,这可能是因为语句中存在未定义的行为,因此无限循环是允许的行为,也可能是因为语句中的某些内容执行无限循环


由于您尚未提供if语句中使用的例程或宏的实现或规格,因此无法进行进一步的诊断。

如果先前的比较表明该值等于零,popeq指令将返回r0中的值。本质上,它就像{…if!search\u str\u entry…return 0;}while1;一样重写代码;。如果指令在第一次尝试时返回零,这将保存指令;如果指令在第二次尝试时返回零,这将实现盈亏平衡;如果指令在第二次尝试后每次尝试都返回一条额外的指令,这将保存指令。我不知道为什么gcc会认为这是一个很好的折衷方案,但在某些情况下确实如此。请使用-s编译,让编译器生成程序集并向我们显示该文件。“无限循环”可能只是一个未填充的重新定位。@supercat:第二次尝试是什么?源代码中没有循环。这只是一个假设,不是一段时间或一段时间。编译器引入的无限循环表示某些未定义的行为或隐藏的无限循环,例如,在if.StrEntry*条目的then子句中的cmemclr内部什么是StrEntry?它是一个人吗?@wildplasser它是一个结构。如果前面的比较表明它等于零,popeq指令将返回r0中的值。本质上,它就像{…if!search\u str\u entry…return 0;}while1;一样重写代码;。如果指令在第一次尝试时返回零,这将保存指令;如果指令在第二次尝试时返回零,这将实现盈亏平衡;如果指令在第二次尝试后每次尝试都返回一条额外的指令,这将保存指令。我不知道为什么gcc会认为这是一个很好的折衷方案,但在某些情况下确实如此。请使用-s编译,让编译器生成程序集并向我们显示该文件。“无限循环”可能只是一个未填充的重新定位。@supercat:第二次尝试是什么?源代码中没有循环。这只是一个假设,不是一段时间或一段时间。编译器引入的无限循环表示某些未定义的行为或隐藏的无限循环,例如,在if.StrEntry*条目的then子句中的cmemclr内部什么是StrEntry?“是一个人吗?”威尔德普拉斯说,“是一个建筑。”。
static inline void cmemclr(void *buf, u32 size)
{
    u8 *dst = (u8*)buf;

    while(--size >= 0){
        dst[size] = 0;
    }
}