【问题标题】:Undefined behavior caused by not proper memory reusing内存重用不当导致的未定义行为
【发布时间】:2014-09-10 05:07:25
【问题描述】:

标准引用如下示例(3.8/7 N3797):

struct C 
{
    int i;
    void f();
    const C& operator=( const C& );
};

const C& C::operator=( const C& other) 
{
    if ( this != &other ) 
    {
        this->~C(); // lifetime of *this ends
        new (this) C(other); // new object of type C created
        f(); // well-defined
    }
return *this;
}

C c1;
C c2;
c1 = c2; // well-defined
c1.f(); // well-defined; c1 refers to a new object of type C

如果我们如下实现operator=,是否存在UB:

const C& C::operator=( const C& other) 
{
    if ( this != &other ) 
    {                        // Note that there is no more explcicitly destructor call,
                             // since at the time of memory reusing the lifetime of 
                             // this is still going on
        new (this) C(other); // new object of type C created
        f(); // well-defined
    }
return *this;
}

相关引用是:

如果,在对象的生命周期之后已经结束并且在存储之前 被占用的对象被重用或释放,一个新的对象被 在原始对象占用的存储位置创建,a 指向原始对象的指针,引用的引用 到原始对象,或者原始对象的名称将 自动引用新对象,并且一旦生命周期 新对象已启动,可用于操作新对象

没有规则:“在存储位置创建一个新对象,而不是一个对象占用”。 同时,我们有一个适合const 对象的规则。很明显:

第 3.8/9 节:

在 const 对象的存储位置创建一个新对象 静态、线程或自动存储持续时间占用,或者,在 这种 const 对象在其之前占用的存储位置 生命周期结束会导致未定义的行为。

【问题讨论】:

    标签: c++ constructor


    【解决方案1】:

    相关规则是这样的:

    3.8/4 程序可以通过重用对象占用的存储空间或通过 显式调用具有非平凡析构函数的类类型对象的析构函数。对于一个对象 具有非平凡析构函数的类类型,程序不需要显式调用析构函数 在对象占用的存储空间被重新使用或释放​​之前;但是,如果没有明确调用 析构函数,或者如果 delete-expression (5.3.5) 不用于释放存储,则不应使用析构函数 隐式调用并且任何依赖于析构函数产生的副作用的程序都未定义 行为。

    你写的例子是合法的,因为C 有一个微不足道的析构函数。

    【讨论】:

    • 确实,谢谢。但我还有一个问题。当我们重用内存时,生命周期仍在继续。 3.8/7 不包括这种情况,对吧?
    • 3.8/7 适用于lefitime结束的情况。这让我很困惑。
    • **3.8/1** The lifetime of an object of type T ends when ... the storage which the object occupies is reused or released.
    • 我知道。但是在对象的生命周期结束之后,在对象占用的存储空间被重用或释放之前,会创建一个新对象[...]意味着生命周期已经结束之前(即在我们开始创建新对象之前)我们创建新对象的时间。
    • 只有通过显式调用析构函数来结束生命周期,才能存在“生命周期已结束”和“存储被重用或释放”之间的差距。
    猜你喜欢
    • 2014-06-22
    • 2020-05-04
    • 2016-04-09
    • 2014-08-23
    • 2014-08-11
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多