174 lines
4.7 KiB
C++
174 lines
4.7 KiB
C++
/***
|
|
*ehvecdtr.cxx - EH-aware version of destructor iterator helper function
|
|
*
|
|
* Copyright (c) 1990-2001, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* These functions are called when constructing and destructing arrays of
|
|
* objects. Their purpose is to assure that constructed elements get
|
|
* destructed if the constructor for one of the elements throws.
|
|
*
|
|
* Must be compiled using "-d1Binl" to be able to specify __thiscall
|
|
* at the user level
|
|
*
|
|
*Revision History:
|
|
* 10-11-93 JDR Module created
|
|
* 05-09-94 BES Module adapted for CRT source conventions
|
|
* 05-13-94 SKS Remove _CRTIMP modifier
|
|
* 10-10-94 CFW Fix EH/SEH exception handling.
|
|
* 10-17-94 BWT Disable code for PPC.
|
|
* 11-09-94 CFW Back out 10-10-94 change.
|
|
* 02-08-95 JWM Mac merge.
|
|
* 04-14-95 JWM Re-fix EH/SEH exception handling.
|
|
* 04-17-95 JWM Restore non-WIN32 behavior.
|
|
* 04-27-95 JWM EH_ABORT_FRAME_UNWIND_PART now #ifdef ALLOW_UNWIND_ABORT.
|
|
* 05-17-99 PML Remove all Macintosh support.
|
|
* 05-20-99 PML Turn off __thiscall for IA64.
|
|
* 07-12-99 RDL Image relative fixes under CC_P7_SOFT25.
|
|
* 03-15-00 PML Remove CC_P7_SOFT25, which is now on permanently.
|
|
*
|
|
****/
|
|
|
|
#ifdef _WIN32
|
|
#if defined(_NTSUBSET_)
|
|
extern "C" {
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntstatus.h> // STATUS_UNHANDLED_EXCEPTION
|
|
#include <ntos.h>
|
|
#include <ex.h> // ExRaiseException
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#include <cruntime.h>
|
|
#include <ehdata.h>
|
|
#include <eh.h>
|
|
|
|
#if defined (_M_IX86)
|
|
#define CALLTYPE __thiscall
|
|
#else
|
|
#define CALLTYPE __stdcall
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
|
|
void __stdcall __ArrayUnwind(
|
|
void* ptr, // Pointer to array to destruct
|
|
size_t size, // Size of each element (including padding)
|
|
int count, // Number of elements in the array
|
|
void(CALLTYPE *pDtor)(void*) // The destructor to call
|
|
);
|
|
|
|
|
|
void __stdcall __ehvec_dtor(
|
|
void* ptr, // Pointer to array to destruct
|
|
size_t size, // Size of each element (including padding)
|
|
int count, // Number of elements in the array
|
|
void(CALLTYPE *pDtor)(void*) // The destructor to call
|
|
){
|
|
int success = 0;
|
|
|
|
// Advance pointer past end of array
|
|
ptr = (char*)ptr + size*count;
|
|
|
|
__try
|
|
{
|
|
// Destruct elements
|
|
while ( --count >= 0 )
|
|
{
|
|
ptr = (char*)ptr - size;
|
|
(*pDtor)(ptr);
|
|
}
|
|
success = 1;
|
|
}
|
|
__finally
|
|
{
|
|
if (!success)
|
|
__ArrayUnwind(ptr, size, count, pDtor);
|
|
}
|
|
}
|
|
|
|
static int ArrayUnwindFilter(EXCEPTION_POINTERS* pExPtrs)
|
|
{
|
|
EHExceptionRecord *pExcept = (EHExceptionRecord*)pExPtrs->ExceptionRecord;
|
|
|
|
switch(PER_CODE(pExcept))
|
|
{
|
|
case EH_EXCEPTION_NUMBER:
|
|
terminate();
|
|
#ifdef ALLOW_UNWIND_ABORT
|
|
case EH_ABORT_FRAME_UNWIND_PART:
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
#endif
|
|
default:
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
}
|
|
|
|
void __stdcall __ArrayUnwind(
|
|
void* ptr, // Pointer to array to destruct
|
|
size_t size, // Size of each element (including padding)
|
|
int count, // Number of elements in the array
|
|
void(CALLTYPE *pDtor)(void*) // The destructor to call
|
|
){
|
|
// 'unwind' rest of array
|
|
|
|
__try
|
|
{
|
|
while ( --count >= 0 )
|
|
{
|
|
ptr = (char*) ptr - size;
|
|
(*pDtor)(ptr);
|
|
}
|
|
}
|
|
__except( ArrayUnwindFilter(exception_info()) )
|
|
{
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
void __stdcall __ehvec_dtor(
|
|
void* ptr, // Pointer to array to destruct
|
|
unsigned size, // Size of each element (including padding)
|
|
int count, // Number of elements in the array
|
|
void(CALLTYPE *pDtor)(void*) // The destructor to call
|
|
){
|
|
// Advance pointer past end of array
|
|
ptr = (char*)ptr + size*count;
|
|
|
|
try
|
|
{
|
|
// Destruct elements
|
|
while ( --count >= 0 )
|
|
{
|
|
ptr = (char*)ptr - size;
|
|
(*pDtor)(ptr);
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
// If a destructor throws an exception, unwind the rest of this
|
|
// array
|
|
while ( --count >= 0 )
|
|
{
|
|
ptr = (char*) ptr - size;
|
|
try {
|
|
(*pDtor)(ptr);
|
|
}
|
|
catch(...) {
|
|
// If any destructor throws during unwind, terminate
|
|
terminate();
|
|
}
|
|
}
|
|
|
|
// After array is unwound, rethrow the exception so a user's handler
|
|
// can handle it.
|
|
throw;
|
|
}
|
|
}
|
|
|
|
#endif
|