当前位置: 首页 > 知识库问答 >
问题:

(VC++)未初始化变量的运行时检查:测试是如何实现的?

桂智志
2023-03-14

我在试着理解这个测试到底做了什么。这个玩具代码

int _tmain(int argc, _TCHAR* argv[])
{
    int i;
    printf("%d", i);
    return 0;
}

编译成以下内容:

int _tmain(int argc, _TCHAR* argv[])

{012C2DF0推ebp
012C2DF1 mov ebp,esp
012C2DF3 sub esp,0D8H
012C2DF9推EBX
012C2DFA推ESI
012C2DFB推edi
012C2DFB lea edi,[ebp-0D8h]
012C2E02 mov ecx,36H
012C2E07 mov eax,0CCCCCCCH
012C2E0C rep stos dword ptr ES:[edi]
012C2E0E mov BY TE ptr[ebp-0D1h],0

int i;
printf("%d", i);

012C2E15 cmp字节ptr[ebp-0D1h],0
012C2E1C jne WMAIN+3BH(012C2E2BH)
012C2E1E推12C2E5CH
012C2E23调用__RTC_UNINITUSE(012C10B9H)
012C2E28添加esp,4
012C2E2B mov esi,esp
012C2E2D mov eax,dword ptr[i]
012C2E30推eax
012C2E31推12C5858H
0 12C2E36调用dword ptr DS:[12C9114H]
012C2E3C添加esp,8
012C2E3F cmp esi,esp
012C2E41调用__RTC_CHECKESP(012C1140H)

return 0;

012C2E46 xor eax,eax
}012C2E48 pop EDI
012C2E49 pop ESI
012C2E4A pop EBX
012C2E4B添加esp,0D8H
012C2E51 cmp ebp,esp
012C2E53调用__RTC_CHECKESP(012C1140H)
012C2E58 mov esp,ebp
012C2E5A pop ebp
012C2E5B ret

强调的5行是唯一通过正确初始化变量i而删除的行。行'push12c2e5ch,call__rtc_uninituse'调用显示错误框的函数,指针指向包含变量名(“i”)的字符串作为参数。

我不能理解的是执行实际测试的3行:

012C2E0E mov字节ptr[ebp-0D1h],0
012C2E15 cmp字节ptr[ebp-0D1h],0
012C2E1C jne WMAIN+3BH(012C2E2BH)

有事吗?也许探针是为了完全不同的东西,比如说测试某个字节是否可写?

共有1个答案

谯志诚
2023-03-14

[ebp-0D1h]是编译器用来跟踪变量“初始化”状态的临时变量。如果我们稍微修改一下源码,就会更清楚:

int _tmain(int argc, _TCHAR* argv[])
{
    int i, j;
    printf("%d %d", i, j);
    i = 1;
    printf("%d %d", i, j);
    j = 2;
    return 0;
}

生成以下内容(跳过无关部分):

mov DWORD PTR [ebp-12], -858993460      ; ccccccccH
mov DWORD PTR [ebp-8], -858993460       ; ccccccccH
mov DWORD PTR [ebp-4], -858993460       ; ccccccccH
mov BYTE PTR $T4694[ebp], 0
mov BYTE PTR $T4693[ebp], 0

在prolog中,变量用0xCC填充,两个跟踪变量(一个用于i,一个用于j)设置为0。

; 7    :        printf("%d %d", i, j);    
    cmp BYTE PTR $T4693[ebp], 0
    jne SHORT $LN3@main
    push    OFFSET $LN4@main
    call    __RTC_UninitUse
    add esp, 4
$LN3@main:
    cmp BYTE PTR $T4694[ebp], 0
    jne SHORT $LN5@main
    push    OFFSET $LN6@main
    call    __RTC_UninitUse
    add esp, 4
$LN5@main:
    mov eax, DWORD PTR _j$[ebp]
    push    eax
    mov ecx, DWORD PTR _i$[ebp]
    push    ecx
    push    OFFSET $SG4678
    call    _printf
    add esp, 12                 ; 0000000cH
if ( $T4693 == 0 )
  _RTC_UninitUse("j");
if ( $T4694 == 0 )
  _RTC_UninitUse("j");
printf("%d %d", i, j);
; 8    :        i = 1;    
    mov BYTE PTR $T4694[ebp], 1
    mov DWORD PTR _i$[ebp], 1
; 10   :        j = 2;
mov BYTE PTR $T4693[ebp], 1
mov DWORD PTR _j$[ebp], 2
 类似资料:
  • 我想知道是否有一种方法可以检查变量是否已经初始化。例如:

  • 我想知道是否有办法检查变量是否已初始化。例如:

  • 本文向大家介绍tensorflow 初始化未初始化的变量实例,包括了tensorflow 初始化未初始化的变量实例的使用技巧和注意事项,需要的朋友参考一下 今日在Stack Overflow上看到一个问如何只初始化未初始化的变量,有人提供了一个函数,特地粘贴过来共大家品鉴: 通过tf.global_variables()返回一个全局变量的列表global_vars, 然后以python列表解析式的

  • 问题内容: 我需要使用类似于php的isset函数的东西。我知道php和java截然不同,但是php是我先前类似编程知识的唯一基础。是否有某种方法可以返回一个布尔值,用于确定实例变量是否已初始化。例如… 到目前为止,我遇到了这个问题,当我的程序试图隐藏或删除尚未构造的对象时,出现运行时错误。 问题答案: 假设您对是否已为变量 明确赋值 感兴趣,答案是“不是真的”。但绝对的字段(实例变量或类变量)尚

  • 我尝试了这些编译器: gcc 4.9.2 with-wall-wextra 启用所有警告的Microsoft Visual C++2013

  • 我有以下Java代码: 但是,当我运行它时,它会抛出以下错误: 我在do之前初始化了变量。while 循环,并在 try. 中设置值。捕获循环。似乎尚未设置该变量。抱歉,如果这是一个相当基本的问题,但我似乎无法弄清楚。