whats problem with this code? msvs2005  
Author Message
Av0id





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

hello, it's my first post here, i have little problem, i'am trying to build minimal executable, but i can't, the main problem is 'unresolved external symbol _memcpy'

main project options is /NODEFAULTLIB, enabled intrinsic-functions and changed entry-point to WinMainA

here it my simple code which reproduce error:

#include <windows.h>

// Constants

struct _TEST
{
char test1[256];
char *test2;
int test3;
};

// Main code

void _test(_TEST *tst)
{
ZeroMemory(tst,sizeof(_TEST));
tst->test3=666;
}

int __stdcall WinMainA()
{
_TEST mmm;

_test(&mmm);
ExitProcess(mmm.test3);
}

ps. this code successfully compiled on msvs2002-2003, please, help me to solve this, thanks



Visual C++8  
 
 
Mike Danes





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

Are you talking about memcpy or memset ZeroMemory is a macro that leads to memset so its no wonder what this code needs memset. In addition enabling inrinsic functions is only a hint to the compiler to use them, the compiler may chose to not use intrinsics.

You have 2 options:

  • Provide your own memset function. I got a 8 kb exe using a basic memset.
  • Don't use NODEFAULTLIB but link to the static version of CRT. This allows the compiler to use the memset from CRT and since you don' use the entrypoint from CRT the rest of the CRT will not be linked in. I got a 13.5 kb exe which is still quite small.

 
 
Holger Grund





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

I'm not sure what exactly you're trying to achive, but in addition to what Mike said, you have a couple of options to reduce size of your executable:

1) Don't use memset, just use a parameterless functional-notation cast expression:

*tst = _TEST();

2) Don't use /Zl or /NODEFAULTLIB but bypass startup and cleanup. Of course, you must be very careful to avoid things that require CRT initialization or cleanup. E.g. just link with /entry WinMain. This should reduce the EXE size quite significantly, but of course, you don't get any automatic initialization/destructions of globals, local statics, handling exceptions escaping from main, FP initialization, /GS checks and a gazillion of other things ...

-hg


 
 
Mike Danes





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

"1) Don't use memset, just use a parameterless functional-notation cast expression:

*tst = _TEST();"

And how do you think the compiler will zero it out, especially given the size of the structure


 
 
Holger Grund





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

Well, the code generators I've worked on (one of them trying to be highly compatible to VC on the ABI level while heavily optimized for performance for their own set of processors) used different intrinsics for compiler-generated initialization. Oc, VC doesn't ship with a stripped down version with just the compiler support code but other compilers do.

But that code, also has the additional benefit of signaling required alignment to the codegen, which allows it use just a plain rep stosd without having to account for additional alignment on either side. While VC's optimization isn't really strong at the microlevel it's probably still smart enough to figure out that an inlined rep stosd is a much better choice than calling a plain dumb memset here.

I don't quite get your argument about the size of the structure. It certainly is large enough to warrant using a loop-construct and certainly too small for vectorized execution to amortize set up costs.

So, in conclusion, I actually believe it does make a difference for a decent codegen (and I'd even bet VC 7.1+ would be good enough here, too). But then, I don't have access to a copy right now.

-hg


 
 
Brian Kramer





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

I did a quick test with Holger's code. The compiler generates a memset to construct the temporary, followed by a rep movs instruction to fill the destination *tst. Here's a variation that only uses rep movs. The static variable lands in memory that is assumed to be initialized to zero by the compiler. (Remove static and you get code similar to Holger's).

void _test(_TEST *tst)
{
static _TEST empty = {};
*tst = empty;
tst->test3=666;
}


 
 
Mike Danes





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

" which allows it use just a plain rep stosd without having to account for additional alignment on either side"

I thought so too a while ago but it does not seem to happen. Whatever optimizations flags I have tried the compiler keeps using memset.

"I don't quite get your argument about the size of the structure. It certainly is large enough to warrant using a loop-construct and certainly too for vectorized execution to amortize set up costs."

Well, I see you got my point. If it weren't for the char array in that struct the compiler would have used something along these lines

xor eax, eax

mov [ebp-4], eax

mov [ebp-8], eax

instead of calling memset.


 
 
Holger Grund





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

I don't have a VC 8 here, but what you say sounds like a bug to me (I guess, it's obvious that we're taking about compiling things with optimizations enabled). But I can see how VC 7.1 isn't any smarter. It does a rep stosd into a temporary followed a rep movsd. Maybe a placement new would do. But well, that's really embarassing.

-hg


 
 
Av0id





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

sorry, it's my typo the problem is in '_memset', what i try to achieve i'm trying to get rid of CRT and default libs, that's all

in vs2003 ZeroMemory (memset) in same project compiled to 'rep stosx' without CRT and additional lib's (without unresolved external symbols)

and another thing i noticed, when i trying to compile this, it compiles without error's, but this code doesn't generate 'rep stosx':

struct _TEST
{
//char test1[256];
char *test2;
int test3;
};

// Main code

void _test(_TEST *tst)
{
ZeroMemory(tst,sizeof(_TEST));
tst->test3=666;
}

ps. it's possible to redefine intrinsic function (_memset for example) or it's better to redefine ZeroMemory in older VS i can
redefine intrinsic functiondo it, but not in 2005

thanks for help


 
 
Mike Danes





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

"in vs2003 ZeroMemory (memset) in same project compiled to 'rep stosx' without CRT and additional lib's "

You were lucky probably. I had a similar problem when using VS2003.

"and another thing i noticed, when i trying to compile this, it compiles without error's, but this code doesn't generate 'rep stosx':"

Yes, as I already stated in another post if the array is not there then the compiler just zero out a register and simply writes that register value to test2 and test3 members.

"ps. it's possible to redefine intrinsic function (_memset for example) or it's better to redefine ZeroMemory in older VS i can redefine intrinsic functiondo it, but not in 2005"

You can redefine ZeroMemory (it's a macro) but keep in mind that if the compiler needs to zero out some memory somewhere it will try to use memset, not ZeroMemory. As for redefining the intrinsic function I don't know if it's possible. After all it's not even a function. It's some code that is generated by the compiler and inlined in your function.

"i'm trying to get rid of CRT and default libs, that's all"

I just hope you have a good reason for this


 
 
Av0id





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

ok, i solved my problem with this code:

#pragma function(memset)

extern "C"
void * __cdecl
memset(void * const s,
int c,
size_t n)
{
unsigned char * const p = reinterpret_cast<unsigned char*>(s);
for ( unsigned i = 0; i != n; ++i )
pIdea = static_cast<unsigned char>(c);
return s;
}

thanks to everyone for help


 
 
Brian Kramer





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

"i'm trying to get rid of CRT and default libs, that's all"

I just hope you have a good reason for this

I'm also curious why this is a requirement. Is this for an embedded device where every byte counts

The longer you develop against VS2005, the more you may uncover more compiler dependencies against the CRT. Developing sans the CRT was never really a requirement in Visual Studio, so you're pursuing unsupported scenarios.

Brian


 
 
Mike Danes





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

" the more you may uncover more compiler dependencies against the CRT"

No, it's not that bad . That if you stay away from various C++ "advanced" features like exceptions, RTTI, static storage objects that have constructors and/or destructors etc. Keep in mind that the Windows kernel & drivers are compiled with the same compiler but there is no trace of msvcrt in kernel space, just some self contained functions like wcscpy, wcslen, atoi etc. that are exported from the kernel executable itself.


 
 
Brian Kramer





PostPosted: Visual C++ Language, whats problem with this code? msvs2005 Top

We're on the same page. I think the list you give, along with the "etc," is reason enough to not care about eliminating the CRT dependency. ATL had a "minimal CRT dependency" to help on ActiveX downloads, but other than that I'm generally against doing hacks such as above for an artificial requirement. Or is the requirement legitimate