isocpp / isocpp/CppCoreGuidelines

How do we handle "immortal" pointers that are reachable for entire lifetime of an app?

Open
#1,068 10 comments 0 reactions 1 assignee View on GitHub

@hsutter is already working on this.

Since Nov 27, 2017.

Dominant language
CSS
Stars
45.3k
Forks
5.6k
PR merge metrics
No merged PRs in 30d

Description

The "Google C++ Style Guide" forbids variables of static storage duration and Titus Winters in
"CppCon 2017: Titus Winters “Hands-On With Abseil" ( https://www.youtube.com/watch?v=xu7q8dGvuwk ) gave some of the engineering reasons behind this rules which seems to be entirely reasonable.

In short , at the global namespace, Google's prefers this

#include <iostream>

const std::string& str() {
  static std::string* s = new std::string("Hello");
  return *s;
}

main() {
  std::cout << str();
}

over

#include <iostream>

const std::string str("Hello");

main() {
  std::cout << str;
}

as new std::string("Hello") is intended to be reachable for the entire lifetime of the app and thus it's not strictly necessary to run std::string's dtor and deallocate memory as the OS will eventually recover the memory when process finally terminates. In fact it helps if new std::string("Hello") is never deleted as we can avoid the complication of coordinating its destruction order with respect to other static variables/threads that may refer to it when a program exits main.

In this situation, I assume static gsl::owner<std::string*> s = new std::string("Hello"); is not appropriate as the code checking tools should warn that a delete s is missing?

Instead, does it makes sense to have a gsl::immortal to indicate that the object is intentionally never deleted? e.g.

const std::string& str() {
  static gsl::immortal<std::string*> s = new std::string("Hello");
  return *s;
}

In addition, we could complement gsl::immortal with gsl::make_immortal(...) as this give us :

  1. Ability to allocate from a mem pool to reduce possible memory fragmentation.
  2. Convenient opportunity to inform a mem leak detector that the mem alloc is intentionally not matched by a dealloc.

This would be especially helpful for the light-weight mem leak detector that's built into MSVC's debug CRT.
e.g.

namespace gsl {
  template<typename T, typename Args>
  gsl::immortal<T> make_immortal(Args&&... a) {
    T p;
    int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 
    _CrtSetDbgFlag(flag & ~_CRTDBG_ALLOC_MEM_DF); 
    try {
      p = new T(std::forward<Args>(a)...);
    }
    catch(...) {
      _CrtSetDbgFlag(flag); 
      throw;
    }
    _CrtSetDbgFlag(flag); 
    return p;
  }
}

const std::string& str() {
  static auto s = gsl::make_immortal<std::string*>("Hello");
  return *s;
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.