在IDA创建的几乎每个反汇编中,都有几个标记为nullsub_的函数,根据IDA,这些函数不返回null(只是ret指令)。

那么,这些是什么,为什么它们在数据库中?

评论

我认为您的意思是“根据IDA,它们什么也不会返回”(即一条简单的“ ret”指令)。这与null不同。例如,当过程是占位符时,就会发生这种情况。

@peterferrie,你是对的。感谢您的纠正。

#1 楼

我从C ++的角度回答,其他语言也有不同的原因。
这些函数有合法用途,即使它们仅不过是

void func(/* any args */) {}


我想到的一个例子是虚函数,该虚函数在基类中不执行任何操作,但在派生类中被覆盖。一个类似的示例是一个模板函数,其一般情况为空,而专门化条件为空。

另一种情况是静态变量。必须在程序结尾处调用静态变量析构函数,该函数通常在首次访问变量时使用atexit来注册析构函数回调。我记得,C ++标准说不会调用没有可观察行为的析构函数,但是我仍然看到MSVC 6.0将nullsub s都注册为析构函数。

全局变量遵循类似于静态变量的规则。

根据编译器的说法,另一种可能性是一个完全无效的函数。该函数必须存在,以防某些情况(例如,另一个不知道实现为空的编译单元)试图调用它,但其主体为空。
请记住,“根据编译器”并不总是等同于编码人员的理解。我本人曾经编写了一个清理函数,该函数做了很多工作,但是由于错误,它采用了值而不是引用的参数。编译器在没有任何警告的情况下将整个功能体优化为{}。糟糕。

#2 楼

DCoders的回答很好,但是其他原因包括:

在调试和发行版中,函数的主体#ifdef可能已被删除,但是保留函数调用以避免更改代码流。 br />
一个示例是调试打印功能

另一个原因是允许打补丁。这个很弱。

评论


因此,尽管优化标志处于打开状态,但编译器可能会故意将其保留?

– PhoeniX
13-10-10在6:58

并不是所有的优化都是平等的,也不是所有的编译器都是平等的。我想的示例来自非ARM / x86 CPU或80年代/ 90年代的代码。

– Simeon朝圣者
13年10月10日在22:23

#3 楼

编译器可能会在指令之间随机插入哑哑null_sub,以使IDA反编译器混乱。这样IDA可能会生成无意义的变量名,增加了逆向工程师理解工作流,连接点的工作量。