对象内存模型的有关问题: 对象数组的构造过程如果失败了,被构造的对象会被析构么

对象内存模型的问题: 对象数组的构造过程如果失败了,被构造的对象会被析构么?
<<深入理解C++对象内存模型>>这本书上对于对象数组的构造是这样解释的,编译器会把ctor/dtor的地址都push到堆栈上,作为一个编译器生成的函数参数:

object *pobj=new object[some];会让编译器产生一个函数:
C/C++ code

void objectArrayCtor( (void)(*pCtor)(), (void)(*pDtor), object* pMem, size_t nCount ){
   try{
      for(int c=0;c<nCount;++c){
         pMem[c]->object::object();//构造函数调用
      }
   }...
}


因此object *pobj=new object[some];语句就被编译成了两个调用:
C/C++ code

object *pobj=operator new(some* sizeof(object));
objectArrayCtor( &object::object, &object::~object, pobj, some);


之所以要传入dtor的地址,是为了当ctor循环没有完全成功的时候,例如构造了若干个以后遇到了异常,那么就终止构造并析构已经构造了的对象门。

-------------------问题---------------------

我试验了一下,似乎没有什么事情能使得,当某次执行构造函数失败的时候,编译器自动生成的代码能帮我析构已经构造的那些个对象。下面的小程序是这样的: 构造函数计算i,当s_count=5的时候,遇到除0错误,抛出异常。这个异常并不能触发对象的析构函数。

我不知道编译器为objectArrayCtor传入dtor的地址到底有什么用,怎么样才能触发这个dtor呢?
C/C++ code

#include<stdexcept>
using namespace std;
struct s{
    static int s_count;
    int i;
    s()
    {
        ++s_count;
        printf("ctor %d,%p\n",s_count,this);
        try{
            if(s_count==5)throw std::range_error("divide 0!");
            i=10/(s_count-5); //divide by 0 when s_count=5
        }
        catch(exception& e){
            throw e;
        }
    }
    ~s()
    {
        printf("dtor %p\n",this);
    }
};
int s::s_count=0;
int main(int,char*[]){ 
    s* ps=new s[10];
    delete[]ps;
    return 0;
} 



------解决方案--------------------
标准保证 stack unwinding 过程中,已构造的数组对象按逆序析够。主楼的程序导致 uncaught exception,因此没有发生 stack unwinding,因此没有析够,改成下面这样就能看到效果了。
C/C++ code

#include<stdexcept>
using namespace std;
struct s{
    static int s_count;
    int i;
    s()
    {
        ++s_count;
        printf("ctor %d,%p\n",s_count,this);
        try{
            if(s_count==5)throw std::range_error("divide 0!");
            i=10/(s_count-5); //divide by 0 when s_count=5
        }
        catch(exception& e){
            throw e;
        }
    }
    ~s()
    {
        printf("dtor %p\n",this);
    }
};
int s::s_count=0;
int main(int,char*[]){ 
    try
    {
     s* ps=new s[10];
     delete[]ps;
    }
    catch (...) // stack unwinding happened before this point.
    {
    }
    return 0;
}