问题描述
我参与了其中的一种挑战,即您尝试生成尽可能小的二进制文件,因此我在没有C或C ++运行时库(RTL)的情况下构建程序 。我没有链接到DLL版本或静态版本。我什至没有 #include
头文件。我的工作正常。
某些RTL函数(例如 memset()
)可能很有用,所以我尝试了添加我自己的实现。它在Debug版本中运行良好(即使在编译器生成对 memset()
的隐式调用的地方)。但是在Release版本中,出现一个错误,提示我无法定义内部函数。您会看到在Release版本中启用了内部函数,并且 memset()
是内部函数。
我会我喜欢在我的发行版中为 memset()
使用内在函数,因为它可能是内联的,并且比我的实现更快,更小。但我似乎是22级。如果我未定义 memset()
,则链接程序会抱怨它未定义。如果确实定义了它,则编译器会抱怨我无法定义内部函数。
有人知道定义,声明,#的正确组合吗?
Visual Studio 2008,x86,Windows XP +。
pragma ,以及编译器和链接器标志来获取内部函数而又不增加RTL开销? / p>
使问题更具体:
外部 C void * __cdecl memset(void *,int,size_t);
#ifdef IMPLEMENT_MEMSET
void * __cdecl memset(void * pTarget,int value,size_t cbTarget){
char * p = reinterpret_cast< char *>(pTarget);
而(cbTarget> 0){
* p ++ = static_cast< char>(值);
--cbTarget;
}
返回pTarget;
}
#endif
struct MyStruct {
int foo [10];
int酒吧;
};
int main(){
MyStruct等等;
memset(& blah,0,sizeof(blah));
return blah.bar;
}
我这样构建:
cl / c / W4 / WX / GL / Ob2 / Oi / Oy / Gs- / GF / Gy native.cpp
链接/ SUBSYSTEM:CONSOLE / LTCG / DEBUG / NODEFAULTLIB / ENTRY:main native.obj
如果我使用<$ c的实现进行编译$ c> memset(),出现编译器错误:
错误C2169: memset :内在函数,无法定义
如果在不执行的情况下进行编译memset()
,出现链接器错误:
错误LNK2001:无法解析的外部符号_memset
我想我终于找到了解决方案:
首先,在头文件中使用编译指示声明 memset()
,如下所示:
extern C void * __cdecl memset(void *,int,size_t);
#pragma内在(内存集)
这允许您的代码调用 memset()
。在大多数情况下,编译器将内联版本。
第二个在单独的实现文件中提供实现。防止编译器抱怨重新定义内部函数的技巧是首先使用另一个编译指示。像这样:
#pragma function(memset)
void * __cdecl memset(void * pTarget,int value,size_t cbTarget){
unsigned char * p = static_cast< unsigned char *>(pTarget);
而(cbTarget--> 0){
* p ++ = static_cast< unsigned char>(值);
}
返回pTarget;
}
这为优化程序决定不使用内在函数的情况提供了一种实现
最大的缺点是您必须禁用整个程序优化(/ GL和/ LTCG)。我不确定为什么。如果有人找到了在不禁用全局优化的情况下执行此操作的方法,请发出提示。
I'm involved in one of those challenges where you try to produce the smallest possible binary, so I'm building my program without the C or C++ run-time libraries (RTL). I don't link to the DLL version or the static version. I don't even #include
the header files. I have this working fine.
Some RTL functions, like memset()
, can be useful, so I tried adding my own implementation. It works fine in Debug builds (even for those places where the compiler generates an implicit call to memset()
). But in Release builds, I get an error saying that I cannot define an intrinsic function. You see, in Release builds, intrinsic functions are enabled, and memset()
is an intrinsic.
I would love to use the intrinsic for memset()
in my release builds, since it's probably inlined and smaller and faster than my implementation. But I seem to be a in catch-22. If I don't define memset()
, the linker complains that it's undefined. If I do define it, the compiler complains that I cannot define an intrinsic function.
Does anyone know the right combination of definition, declaration, #pragma
, and compiler and linker flags to get an intrinsic function without pulling in RTL overhead?
Visual Studio 2008, x86, Windows XP+.
To make the problem a little more concrete:
extern "C" void * __cdecl memset(void *, int, size_t);
#ifdef IMPLEMENT_MEMSET
void * __cdecl memset(void *pTarget, int value, size_t cbTarget) {
char *p = reinterpret_cast<char *>(pTarget);
while (cbTarget > 0) {
*p++ = static_cast<char>(value);
--cbTarget;
}
return pTarget;
}
#endif
struct MyStruct {
int foo[10];
int bar;
};
int main() {
MyStruct blah;
memset(&blah, 0, sizeof(blah));
return blah.bar;
}
And I build like this:
cl /c /W4 /WX /GL /Ob2 /Oi /Oy /Gs- /GF /Gy intrinsic.cpp
link /SUBSYSTEM:CONSOLE /LTCG /DEBUG /NODEFAULTLIB /ENTRY:main intrinsic.obj
If I compile with my implementation of memset()
, I get a compiler error:
error C2169: 'memset' : intrinsic function, cannot be defined
If I compile this without my implementation of memset()
, I get a linker error:
error LNK2001: unresolved external symbol _memset
I think I finally found a solution:
First, in a header file, declare memset()
with a pragma, like so:
extern "C" void * __cdecl memset(void *, int, size_t);
#pragma intrinsic(memset)
That allows your code to call memset()
. In most cases, the compiler will inline the intrinsic version.
Second, in a separate implementation file, provide an implementation. The trick to preventing the compiler from complaining about re-defining an intrinsic function is to use another pragma first. Like this:
#pragma function(memset)
void * __cdecl memset(void *pTarget, int value, size_t cbTarget) {
unsigned char *p = static_cast<unsigned char *>(pTarget);
while (cbTarget-- > 0) {
*p++ = static_cast<unsigned char>(value);
}
return pTarget;
}
This provides an implementation for those cases where the optimizer decides not to use the intrinsic version.
The outstanding drawback is that you have to disable whole-program optimization (/GL and /LTCG). I'm not sure why. If someone finds a way to do this without disabling global optimization, please chime in.
这篇关于如何在不使用运行时库的情况下使用VC ++内部函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!