VS2013下的new[]和delete[]分析
本帖最后由 Crack_Qs 于 2014-9-20 07:11 编辑编译模式:Debug
编译环境:Microsoft Visual Studio Ultimate 2013 (12.0.30501.00) Update 2
//////////////////////////////////////////////////////////////////////////////
一. New[]:
C++代码:
int *lpNum = new int;
汇编代码:
PUSH 0x40 ; new申请的空间大小
CALL XXXXXXXX ; CALL NEW
ADDESP, 0x4 ; _cdecl调用约定的平栈
MOVDWORD PTR SS:, EAX ; 把返回值(申请空间的地址)给临时变量(猜测用于保存)
MOVEAX, DWORD PTR SS: ; 从临时变量中取出地址
MOVDWORD PTR SS:, EAX ; 赋值给函数内的指针
看一下New里面干了什么:
PUSH EBP ; void *New(int nSize);
MOV EBP, ESP ; ebp+0x8 nSize的栈空间
SUB ESP, 0x10
MOV EAX, DWORD PTR SS: ; 取nSize
PUSH EAX ; 压入nSize
CALL malloc ; call malloc
ADD ESP, 0x4 ; _cdecl调用约定的平栈
MOV DWORD PTR SS:, EAX ; 返回值为malloc申请的地址
CMP DWORD PTR SS:, 0x0 ; 如果返回值 == NULL
JNZ SHORT msvcr120.0FB0C2A3
MOV ECX, DWORD PTR SS: ; 取大小
PUSH ECX ; 压入大小
CALL _callnewh ; _callnewh(size)
ADD ESP, 0x4 ; _cdecl调用约定的平栈
TEST EAX, EAX ; 如果返回值等于 NULL
JNZ SHORT msvcr120.0FB0C2A1
LEA ECX, DWORD PTR SS:
CALL bad_alloc ; call bad_alloc
PUSH msvcr120.0FB753D8
LEA EDX, DWORD PTR SS:
PUSH EDX
CALL _CxxThrowException ; CALL _CxxThrowException
JMP SHORT msvcr120.0FB0C266
MOV EAX, DWORD PTR SS: ; 不等于NULL,返回值给EAX,返回到main函数
MOV ESP, EBP
POP EBP
RETN
因VS2013无法查看其实现代码,以下为个人猜测如有错误忘请不吝赐教:
void* _cdecl operator new(unsigned int nSize)_THROW1(_STD bad_alloc)
{
void *lpBuf;
while ((lpBuf = malloc(nSize)) == NULL)
{
if (_callnewh(nSize) == NULL)
{
static const std::bad_alloc nomem;
_RAISE(nomem);
}
}
return lpBuf;
}
二. Delete[]:
C++代码:
int *lpNum = new int;
delete lpNum;
汇编代码:
MOV EAX, DWORD PTR SS: ; 从变量中取出lpNum地址
MOV DWORD PTR SS:, EAX ; 放入临时变量EBP-0xD4
MOV ECX, DWORD PTR SS: ; 从临时变量中取出地址
PUSH ECX ; 压入参数
CALL NewDELET.013011DB ; call delete
ADD ESP, 0x4 ; _cdecl调用约定平栈
CMP DWORD PTR SS:, 0x0 ; 判断临时变量EBP-0xD4中的地址值是否等于NULL
JNZ SHORT NewDELET.01301A54
MOV DWORD PTR SS:, 0x0 ; 如果临时变量EBP-0xD4不为NULL就把临时变量EBP-0xE8填为NULL
JMP SHORT NewDELET.01301A64
MOV DWORD PTR SS:, 0x8123 ; 给lpNum传入一个值0x8123
MOV EDX, DWORD PTR SS: ; 从lpNum取出值
MOV DWORD PTR SS:, EDX ; 临时变量EBP-0xE8填为0x8123
看一下Delete里面干了什么:
PUSH EBP ; void _cdecl operator delete (void *pBuf)
MOV EBP, ESP ; EBP+0x8 pBuf的栈空间
PUSH -0x2
PUSH msvcr120.52499400
PUSH msvcr120.5243FEF0
MOV EAX, DWORD PTR FS:
PUSH EAX
ADD ESP, -0xC
PUSH EBX
PUSH ESI
PUSH EDI
MOV EAX, DWORD PTR DS:
XOR DWORD PTR SS:, EAX
XOR EAX, EBP
PUSH EAX
LEA EAX, DWORD PTR SS:
MOV DWORD PTR FS:, EAX
CMP DWORD PTR SS:, 0x0 ; 判断pBuf是否 == NULL
JNZ SHORT msvcr120.5243A9CB
JMP msvcr120.5243AA68 ; 跳向函数尾部 (return)
PUSH 0x4 ; 4
CALL msvcr120._lock ; call _lock
ADD ESP, 0x4 ; _cdecl调用约定平栈
MOV DWORD PTR SS:, 0x0
MOV EAX, DWORD PTR SS: ; pBuf - 0x20
SUB EAX, 0x20
MOV DWORD PTR SS:, EAX ; 临时变量 = pBuf - 0x20
MOV ECX, DWORD PTR SS: ; 取出运算后的pBuf
MOV EDX, DWORD PTR DS: ; 取pBuf+0x14由此可以判断ebp-0x1c是一个结构体变量结果为1 是个逻辑值
AND EDX, 0xFFFF
CMP EDX, 0x4 ; [+0x14] & 0xffff != 4
JE SHORT msvcr120.5243AA3C
MOV EAX, DWORD PTR SS:
CMP DWORD PTR DS:, 0x1 ; [+0x14] != 0x1
JE SHORT msvcr120.5243AA3C
MOV ECX, DWORD PTR SS:
MOV EDX, DWORD PTR DS:
AND EDX, 0xFFFF ; [+0x14] & 0xffff != 0x2
CMP EDX, 0x2
JE SHORT msvcr120.5243AA3C
MOV EAX, DWORD PTR SS:
CMP DWORD PTR DS:, 0x3 ; [+0x14] != 0x3
JE SHORT msvcr120.5243AA3C
PUSH msvcr120.52321BF8 ; UNICODE "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)"
PUSH msvcr120.5230127C ; UNICODE "%s"
PUSH 0x0 ; NULL
PUSH 0x34 ; __LINE__
PUSH msvcr120.52321C48 ; __FILE__
PUSH 0x2
CALL msvcr120._CrtDbgReportW ; call _CrtDbgReportW : _CrtDbgReportW(0x2,?,0x34,0x0,%s,_BLOCK_TYPE_IS_VALID(pHead->nBlockUse))
ADD ESP, 0x18 ; _cdecl调用约定平栈
CMP EAX, 0x1 ; if( _CrtDbgReportW == 1)
JNZ SHORT msvcr120.5243AA3C
INT3
MOV EDX, DWORD PTR SS:
MOV EAX, DWORD PTR DS:
PUSH EAX ; push [+0x14]
MOV ECX, DWORD PTR SS:
PUSH ECX ; push pBuf
CALL msvcr120._free_dbg ; call _free_dbg : _free_dbg(pbuf,[+0x14])
ADD ESP, 0x8 ; _cdecl调用约定平栈
MOV DWORD PTR SS:, -0x2
CALL msvcr120.5243AA5D ; 调用下面的 _unlock
JMP SHORT msvcr120.5243AA68
PUSH 0x4
CALL msvcr120._unlock ; call _unlock : _unlock(4)
ADD ESP, 0x4 ; _cdecl调用约定平栈
RETN
MOV ECX, DWORD PTR SS: ; 函数尾部
MOV DWORD PTR FS:, ECX
POP ECX
POP EDI
POP ESI
POP EBX
MOV ESP, EBP
POP EBP
RETN
因VS2013无法查看其实现代码,以下为个人猜测如有错误忘请不吝赐教:
void _cdecl operator delete (void *pBuf)
{
_CrtMemBlockHeader * pHead;
if (pBuf == NULL)
{
return;
}
_lock(4);
pHead = ((_CrtMemBlockHeader *)pBuf) - 0x20;
if ((pHead->nBlockUse & 0xFFFF) == 4
|| (pHead->nBlockUse) == 1 || (pHead->nBlockUse & 0xFFFF) == 2
|| (pHead->nBlockUse) == 3
&& (1 == _CrtDbgReport(0x2, __FILE__, __LINE__, NULL,
(pHead->nBlockUse & 0xFFFF) == 4
||(pHead->nBlockUse) == 1 || (pHead->nBlockUse & 0xFFFF) == 2
|| (pHead->nBlockUse) == 3) )
)
{
__asm
{
int 3
}
}
_free_dbg( pBuf, pHead->nBlockUse );
_munlock(4)
return;
}
int _CrtDbgReport( int reportType, const char *filename, int linenumber, const char *moduleName, const char *format [, argument] ... );
一楼备用,请大家指教 {:lol:}谢谢楼主的分析呀,不过我还真是看不太懂呀。。。。可能C基础太差了吧。看来的多努力学习一下这方面的知识呀。。。。 我不懂但我支持楼主的好东西, 支持一下了,感谢 本帖最后由 whypro 于 2014-9-23 08:20 编辑
有源代码非要装逼,网上分析文章一裤衩,在这板块太装逼了。
/***
*new.cxx - defines C++ new routine
*
* Copyright (c) Microsoft Corporation.All rights reserved.
*
*Purpose:
* Defines C++ new routine.
*
*******************************************************************************/
#ifdef _SYSCRT
#include <cruntime.h>
#include <crtdbg.h>
#include <malloc.h>
#include <new.h>
#include <stdlib.h>
#include <winheap.h>
#include <rtcsup.h>
#include <internal.h>
void * operator new( size_t cb )
{
void *res;
for (;;) {
//allocate memory block
res = _heap_alloc(cb);
//if successful allocation, return pointer to memory
if (res)
break;
//call installed new handler
if (!_callnewh(cb))
break;
//new handler was successful -- try to allocate again
}
RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
return res;
}
#else/* _SYSCRT */
#include <cstdlib>
#include <new>
_C_LIB_DECL
int __cdecl _callnewh(size_t size) _THROW1(_STD bad_alloc);
_END_C_LIB_DECL
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{ // try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{ // report no memory
_THROW_NCEE(_XSTD bad_alloc, );
}
return (p);
}
/*
* Copyright (c) 1992-2002 by P.J. Plauger.ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
V3.13:0009 */
#endif/* _SYSCRT */
/***
*dbgdel.cpp - defines C++ scalar delete routine, debug version
*
* Copyright (c) Microsoft Corporation.All rights reserved.
*
*Purpose:
* Defines C++ scalar delete() routine.
*
*******************************************************************************/
#ifdef _DEBUG
#include <cruntime.h>
#include <malloc.h>
#include <mtdll.h>
#include <dbgint.h>
#include <rtcsup.h>
/***
*void operator delete() - delete a block in the debug heap
*
*Purpose:
* Deletes any type of block.
*
*Entry:
* void *pUserData - pointer to a (user portion) of memory block in the
* debug heap
*
*Return:
* <void>
*
*******************************************************************************/
void operator delete(
void *pUserData
)
{
_CrtMemBlockHeader * pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK);/* block other threads */
__TRY
/* get a pointer to memory block header */
pHead = pHdr(pUserData);
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg( pUserData, pHead->nBlockUse );
__FINALLY
_munlock(_HEAP_LOCK);/* release other threads */
__END_TRY_FINALLY
return;
}
#endif/* _DEBUG */
本帖最后由 whypro 于 2014-9-23 08:45 编辑
123
whypro 发表于 2014-9-23 08:37
123
第一点,vs2013确实跟进去没有源码(最起码我这不行,有方法的话欢迎指教)
第二点,别的一些版本确实可以跟进去,但是我对比着跟过,个别细节不一样
第三点,我最近研究vs13的东西,你不喜欢那就算了,我的代码是实打实逆出来的,而非网上抄袭。
哇,这代码分析得不错,支持楼主!!!加油
页:
[1]
2