在几乎所有由 IDA 创建的反汇编中,都有几个函数被标记nullsub_
,根据 IDA,返回什么都没有(只是null
ret
指令)。
那么,这些是什么以及为什么它们在数据库中?
在几乎所有由 IDA 创建的反汇编中,都有几个函数被标记nullsub_
,根据 IDA,返回什么都没有(只是null
ret
指令)。
那么,这些是什么以及为什么它们在数据库中?
我是从 C++ 的角度回答的,其他语言有不同的原因。
这些功能有合法用途,即使它们只不过是
void func(/* any args */) {}
想到的一个例子是一个虚函数,它在基类中什么都不做,但在派生类中被覆盖。一个类似的例子是一个模板函数,它的一般情况是空的,但特化不是。
另一种情况是静态变量。静态变量析构函数必须在程序结束时调用,通常atexit
用于在第一次访问变量时注册析构函数回调。我记得,C++ 标准说可能不会调用没有可观察行为的析构函数,但我已经看到 MSVC 6.0 register nullsub
s 作为析构函数。
全局变量遵循类似于静态变量的规则。
根据编译器的说法,另一种可能性是一个根本不起作用的函数。该函数必须存在以防万一(例如,另一个不知道实现为空的编译单元)尝试调用它,但其主体为空。
请注意,“根据编译器”并不总是等于编码器的理解。我自己曾经写过一个清理函数,它做了很多工作,但错误地将参数按值而不是按引用。编译器在{}
没有任何警告的情况下优化了整个函数体。哎呀。
DCoders 的回答很好,但其他原因包括:
该函数可能在发布版本调试中将主体 #ifdef 去掉,但保留函数调用以避免更改代码流。
一个例子是调试打印功能
另一个原因是允许打补丁。这个是很弱的。
编译器可能会在方向之间随机插入哑 null_sub,以混淆 IDA 反编译器。这样IDA可能会生成无意义的变量名,增加逆向工程师理解工作流程的努力,连接到点......