mainCRTStartup中的疑问

canyingwushang 2010-03-10 11:01:58
今天看了《程序员的自我修养》的第11章,程序默认的入口函数是mainCRTStartup(void) /wmainCRTStartup(void)/WinMainCRTStartup(void)/wWinMainCRTStartup(void).
仔细阅读了mainCRTStartup的实现过程,发现程序在获取操作系统等平台信息时,有这样一句

OSVERSIONINFOA *posvi;
.
.
posvi = (OSVERSIONINFOA *)HeapAlloc(GetProcessHeap(), 0, sizeof(OSVERSIONINFOA));

很明显程序是从堆中分配的内存,但是在后面的代码中发现

if ( !_heap_init(1) ) /* initialize heap */
fast_error_exit(_RT_HEAPINIT); /* write message and die */

这时才刚刚初始化堆空间,那前面从堆中分配内存又是怎么样一回事?
而且《程序员的自我修养》中写的却是posvi 用alloca来分配内存,alloca是从栈中分配内存的,难道MS已经升级了这段代码不成,我的是VS2005!
请赐教~
...全文
584 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
canyingwushang 2010-03-11
  • 打赏
  • 举报
回复
引用 1 楼 lhcwjy 的回复:
mainCRTStartup等入口函数是编译器插入到程序中的crt初始化和清理函数,初始化的一个重要任务就是初始化crt堆,在此之前不能使用crt的分配内存函数。但这句并没有问题。每个进程启动时,系统会为它分配一个默认堆,API函数GetProcessHeap就是取得这个默认堆,而API函数HeapAlloc是从堆中分配内存。
posvi = (OSVERSIONINFOA *)HeapAlloc(GetProcessHeap(), 0, sizeof(OSVERSIONINFOA));

楼上的意思是这两个堆是不一样的呗
canyingwushang 2010-03-11
  • 打赏
  • 举报
回复
引用 4 楼 canyingwushang 的回复:
引用 3 楼 coding_hello 的回复:第一个HeapAlloc明显是用的进程默认堆,即从GetProcessHeap里面分配的后面的heap_init是初始化C Runtime Library的运行时库的堆,平时调用malloc是从这里分配。 不过我的vc6的实现里,没有你上面的第一步啊。。。

我看的是VS2005的版本
C Runtime Library 8.0
canyingwushang 2010-03-11
  • 打赏
  • 举报
回复
引用 3 楼 coding_hello 的回复:
第一个HeapAlloc明显是用的进程默认堆,即从GetProcessHeap里面分配的
后面的heap_init是初始化C Runtime Library的运行时库的堆,平时调用malloc是从这里分配。

不过我的vc6的实现里,没有你上面的第一步啊。。。

看来VS的每个版本的确是有改进啊!
野男孩 2010-03-11
  • 打赏
  • 举报
回复
第一个HeapAlloc明显是用的进程默认堆,即从GetProcessHeap里面分配的
后面的heap_init是初始化C Runtime Library的运行时库的堆,平时调用malloc是从这里分配。

不过我的vc6的实现里,没有你上面的第一步啊。。。

#ifdef WPRFLAG
void wmainCRTStartup(
#else /* WPRFLAG */
void mainCRTStartup(
#endif /* WPRFLAG */

#endif /* _WINMAIN_ */
void
)

{
int mainret;

#ifdef _WINMAIN_
_TUCHAR *lpszCommandLine;
STARTUPINFO StartupInfo;
#endif /* _WINMAIN_ */

/*
* Get the full Win32 version
*/
_osver = GetVersion();

_winminor = (_osver >> 8) & 0x00FF ;
_winmajor = _osver & 0x00FF ;
_winver = (_winmajor << 8) + _winminor;
_osver = (_osver >> 16) & 0x00FFFF ;

#ifdef _MT
if ( !_heap_init(1) ) /* initialize heap */
#else /* _MT */
if ( !_heap_init(0) ) /* initialize heap */
#endif /* _MT */
fast_error_exit(_RT_HEAPINIT); /* write message and die */

#ifdef _MT
if( !_mtinit() ) /* initialize multi-thread */
fast_error_exit(_RT_THREAD); /* write message and die */
#endif /* _MT */

/*
* Guard the remainder of the initialization code and the call
* to user's main, or WinMain, function in a __try/__except
* statement.
*/

__try {

_ioinit(); /* initialize lowio */

#ifdef WPRFLAG
/* get wide cmd line info */
_wcmdln = (wchar_t *)__crtGetCommandLineW();

/* get wide environ info */
_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW();

_wsetargv();
_wsetenvp();
#else /* WPRFLAG */
/* get cmd line info */
_acmdln = (char *)GetCommandLineA();

/* get environ info */
_aenvptr = (char *)__crtGetEnvironmentStringsA();

_setargv();
_setenvp();
#endif /* WPRFLAG */

_cinit(); /* do C data initialize */

#ifdef _WINMAIN_

StartupInfo.dwFlags = 0;
GetStartupInfo( &StartupInfo );

#ifdef WPRFLAG
lpszCommandLine = _wwincmdln();
mainret = wWinMain(
#else /* WPRFLAG */
lpszCommandLine = _wincmdln();
mainret = WinMain(
#endif /* WPRFLAG */
GetModuleHandleA(NULL),
NULL,
lpszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow
: SW_SHOWDEFAULT
);
#else /* _WINMAIN_ */

#ifdef WPRFLAG
__winitenv = _wenviron;
mainret = wmain(__argc, __wargv, _wenviron);
#else /* WPRFLAG */
__initenv = _environ;
mainret = main(__argc, __argv, _environ);
#endif /* WPRFLAG */

#endif /* _WINMAIN_ */
exit(mainret);
}
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
{
/*
* Should never reach here
*/
_exit( GetExceptionCode() );

} /* end of try - except */

}


_CRTIMP extern unsigned int _osver;
_CRTIMP extern unsigned int _winver;
_CRTIMP extern unsigned int _winmajor;
_CRTIMP extern unsigned int _winminor;
白云飘飘飘 2010-03-10
  • 打赏
  • 举报
回复
mainCRTStartup等入口函数是编译器插入到程序中的crt初始化和清理函数,初始化的一个重要任务就是初始化crt堆,在此之前不能使用crt的分配内存函数。但这句并没有问题。每个进程启动时,系统会为它分配一个默认堆,API函数GetProcessHeap就是取得这个默认堆,而API函数HeapAlloc是从堆中分配内存。
posvi = (OSVERSIONINFOA *)HeapAlloc(GetProcessHeap(), 0, sizeof(OSVERSIONINFOA));

64,662

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧