美文网首页
C++ delete this

C++ delete this

作者: 胖子罗 | 来源:发表于2019-12-31 12:21 被阅读0次

    先看一段代码:

    void Isolate::TearDown() {
      TRACE_ISOLATE(tear_down);
    
      tracing_cpu_profiler_.reset();
      if (FLAG_stress_sampling_allocation_profiler > 0) {
        heap_profiler()->StopSamplingHeapProfiler();
      }
    
      // Temporarily set this isolate as current so that various parts of
      // the isolate can access it in their destructors without having a
      // direct pointer. We don't use Enter/Exit here to avoid
      // initializing the thread data.
      PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
      DCHECK_EQ(base::Relaxed_Load(&isolate_key_created_), 1);
      Isolate* saved_isolate =
          reinterpret_cast<Isolate*>(base::Thread::GetThreadLocal(isolate_key_));
      SetIsolateThreadLocals(this, nullptr);
    
      Deinit();
    
      {
        base::LockGuard<base::Mutex> lock_guard(&thread_data_table_mutex_);
        thread_data_table_.RemoveAllThreads();
      }
    
    #ifdef DEBUG
      non_disposed_isolates_--;
    #endif  // DEBUG
    
      delete this;//!!!此处似乎有危险
    
      // Restore the previous current isolate.
      SetIsolateThreadLocals(saved_isolate, saved_data);
    }
    

    上面看到这个Isolate类的成员函数里面竟然调用了delete this的语句,而且后面还有代码需要执行,初看到这个语句心里一惊,尼玛这要出大事情。搜了一下这个工程好多地方有这种写法,看来是故意为之且没问题。有段时间没用c++了复习下,安全使用此语句需要满足以下条件:

    1.确保对象是new出来的;
    2.确保delete完后不会用该对象调用其它(非静态)成员函数;
    3.确保delete完后不能访问对象的任何部分;
    4.确保delete完后this指针不会被访问。

    再回到上面那段代码分析:
    delete下面一行调用了SetIsolateThreadLocals

    void Isolate::SetIsolateThreadLocals(Isolate* isolate,
                                         PerIsolateThreadData* data) {
      base::Thread::SetThreadLocal(isolate_key_, isolate);
      base::Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
    }
    

    传入的两个参数实际为TearDown函数内部两个局部变量,满足条件2、3、4。
    再看TearDown函数调用后情况

    void Isolate::Dispose() {
      i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
      if (!Utils::ApiCheck(!isolate->IsInUse(),
                           "v8::Isolate::Dispose()",
                           "Disposing the isolate that is entered by a thread.")) {
        return;
      }
      isolate->TearDown();
    }
    

    TearDown在Dispose函数末尾调用,满足条件;
    最后看看Dispose函数调用情况:

    SnapshotCreator::~SnapshotCreator() {
      SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
      DCHECK(data->created_);
      Isolate* isolate = data->isolate_;
      isolate->Exit();
      isolate->Dispose();//此处调用
      delete data;
    }
    
    void Shell::OnExit(v8::Isolate* isolate) {
      // Dump basic block profiling data.
      if (i::FLAG_turbo_profiling) {
        i::BasicBlockProfiler* profiler = i::BasicBlockProfiler::Get();
        i::StdoutStream{} << *profiler;
      }
      isolate->Dispose();
      //此处后面还有代码,但是已经没有isolate的引用
    }
    

    从上面看出Dispose函数调用后,基本就不用对象了。
    所以delete this;一般在析构函数或释放对象函数里使用,比如引用计数方式里的使用:

      inline void Unref() { if (--refs == 0) delete this; }
    

    从开发角度讲,我们一般调用第三方封装的类似函数接口即可,尽量不直接这样写,除非源码级别。

    相关文章

      网友评论

          本文标题:C++ delete this

          本文链接:https://www.haomeiwen.com/subject/hdsboctx.html