Visual C ++ __forceinline奇怪的行为 [英] Visual C++ __forceinline strange behavior
问题描述
我试图强制Visual C ++编译器内联特定功能.我知道inline
或__forceinline
只是一个建议.根据 MSDN ,如果编译器无法内联使用
I'm trying to force visual c++ compiler to inline a particular function. I know that inline
or __forceinline
is just a suggestion. According MSDN, if compiler cannot inline function which is marked using __forceinline
keyword then it generates warning:
如果编译器无法内联用__forceinline声明的函数, 它会产生1级警告.
If the compiler cannot inline a function declared with __forceinline, it generates a level 1 warning.
但是我没有得到这样的警告.当我调试我的应用程序时,我看到在反汇编窗口中有一个call <inlined function address>
,即我的函数没有被内联.那么,如何检查我的函数是否已内联?这是否意味着如果未生成警告,则内联函数并将问题放在其他位置?
But I have not got such warning. And when I debug my application I see that there is a call <inlined function address>
in Disassembly window i.e. my function was not inlined. So how can I check is my function was inlined or not? Does it mean that if no warning was generated then function was inlined and the problem somewhere in other place?
这是我的功能:
__forceinline SecByteBlock aes_generate_iv(size_t blockSize)
{
const int seedSize = 32;
SecByteBlock rngSeed(seedSize);
OS_GenerateRandomBlock(false, rngSeed, rngSeed.size());
RandomPool rngp;
rngp.IncorporateEntropy(rngSeed, rngSeed.size());
SecByteBlock aesIV(blockSize);
rngp.GenerateBlock(aesIV, aesIV.size());
return aesIV;
}
在某些情况下,VC ++无法内联功能(来自 MSDN ):
Here is circumstances then VC++ cannot inline function (from MSDN):
- 该函数或其调用者使用/Ob0(调试版本的默认选项)进行编译.
- 函数和调用者使用不同类型的异常处理(一种是C ++异常处理,另一种是结构化异常处理).
- 该函数具有可变的参数列表.
- 该函数使用内联汇编,除非使用/Og,/Ox,/O1或/O2进行编译.
- 该函数是递归的,不附带#pragma inline_recursion(on).使用编译指示时,递归函数将内联到默认深度为16的调用中.要减少内联深度,请使用inline_depth编译指示.
- 该函数是虚拟的,实际上是被调用的.可以内联对虚拟函数的直接调用.
- 程序获取函数的地址,并通过指向函数的指针进行调用.可以内联直接调用已采用其地址的函数.
- 该函数还标有裸露的__declspec修饰符.
推荐答案
同一警告有2个版本:
https://msdn.microsoft. com/en-us/library/aa734011(v = vs.60).aspx
编译器警告(等级1)C4714
Visual Studio 6.0
'function':标记为__forceinline的函数未内联
Compiler Warning (level 1) C4714
Visual Studio 6.0
'function' : function marked as __forceinline not inlined
https://msdn.microsoft.com/en-us/library /a98sb923.aspx
编译器警告(等级4)C4714
Visual Studio 2015
标记为__forceinline的函数'function'未内联
Compiler Warning (level 4) C4714
Visual Studio 2015
function 'function' marked as __forceinline not inlined
因此,要启用警告,例如,在Visual Studio 2015中,默认情况下必须使用4级(/W4)而不是3级(/W3).
So, to enable the warning, for example, in the Visual Studio 2015 you have to use Level 4 (/W4) instead of Level 3 (/W3) as by default.
以下有关如何消除此类编译器行为的建议. 我已经在MSVC2015中解决了这些情况:
Below some advices for how to eliminate such compiler behaviour. I've resolved these set of cases in the MSVC2015:
- 递归调用
-
SomeType SomeType::operator++(int)
/SomeType SomeType::operator--(int)
-
std::string
在__forceinline函数中按值返回
- Recursion calls
SomeType SomeType::operator++(int)
/SomeType SomeType::operator--(int)
std::string
returned by value in __forceinline functions
1.递归调用
template <typename T>
__forceinline T int_log2_floor(T v)
{
ASSERT_GT(v, T(0));
if (1 >= v) return 0;
return T((v >= 2 ? int_log2_floor(v / 2) : 0) + 1); // Warning C4714
}
这里的解决方案之一就是展开递归:
One of solution here is just to unroll the recursion:
template <typename T>
__forceinline T int_log2_floor(T v)
{
ASSERT_GT(v, T(0));
if (1 >= v) return 0;
T ret = 0;
T i = v;
do {
++ret;
i /= 2;
} while (i >= 2);
return ret;
}
2. `SomeType SomeType :: operator ++(int)`/`SomeType SomeType :: operator-(int)`
class SomeType
{
__forceinline SomeType operator++(int) // Warning C4714
{
const auto it = *this;
m_it++;
return it;
}
//...
iterator m_it
};
这个对我有用:
class SomeType;
SomeType operator++(SomeType & r, int);
class SomeType
{
friend SomeType operator++(SomeType & r, int);
//...
iterator m_it
};
__forceinline SomeType operator++(SomeType & r, int)
{
const auto it = r;
r.m_it++;
return it;
// You still can write here `const auto it = *this; m_it++; return it`,
// but i hell don't know why this works.
}
3. __forceinline函数中按值返回的`std :: string`
这真的很奇怪,但是似乎之间存在某种干扰
在inline
-ed函数之间的__forceinline
-ed函数,因为std::string
基本上使用第二个-inline
.
3. `std::string` returned by value in __forceinline functions
This one is really strange, but seems there is some kind of interference between
__forceinline
-ed functions between inline
-ed functions because std::string
basically uses second one - inline
.
template<typename T>
__forceinline std::string int_to_bin(T i, bool first_bit_is_lowest_bit = false) // Warning C4714
{
std::bitset<sizeof(T) * CHAR_BIT> bs(i);
if (!first_bit_is_lowest_bit) {
return bs.to_string();
}
const std::string bs_str = bs.to_string();
return std::string(bs_str.rbegin(), bs_str.rend());
}
由于警告是由按值返回类型触发的,因此解决方案是改为通过参数返回,并按inline
内联:
Because the warning has triggered by return-by-value type, the solution here is to return through the parameter instead and inline by inline
:
template<typename T>
__forceinline void int_to_bin_forceinline(std::string & ret, T i, bool first_bit_is_lowest_bit = false)
{
std::bitset<sizeof(T) * CHAR_BIT> bs(i);
if (!first_bit_is_lowest_bit) {
ret = bs.to_string();
return;
}
const std::string bs_str = bs.to_string();
ret = std::string(bs_str.rbegin(), bs_str.rend());
return;
}
template<typename T>
inline std::string int_to_bin(T i, bool first_bit_is_lowest_bit = false)
{
std::string res;
int_to_bin_forceinline(res, i, first_bit_is_lowest_bit);
return res;
}
不用说,可以通过使用inline
关键字而不是__forceinline
来解决所有3个版本.
Needless to say all 3 versions can be workarounded by the inline
keyword usage instead of the __forceinline
.
这篇关于Visual C ++ __forceinline奇怪的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!