Почему моя статическая функция-член подавляет существование статической переменной на уровне файлов где-то еще? - PullRequest
0 голосов
/ 05 июня 2018

У меня есть тип

struct J : ::std::enable_shared_from_this<J> {
  static ::std::weak_ptr<J>& r() {
    static ::std::weak_ptr<J> _r;
    return _r;
  }
  J() {
    r() = shared_from_this();
  }
};

, который в основном обеспечивает некоторую регистрацию.Однако, когда я включаю статическую функцию r(), где-то еще в программе статическая переменная:

// .cpp
namespace {
  llvm::cl::opt<bool> var("var");
}

как-то ломается, в том смысле, что она закомментирована.Никаких ошибок не возникает, так как var никогда не упоминается по имени, а просто должен добавить переключатель командной строки (слова без привязки J::r).

Что может быть причинойэтот?Я попытался свести пример к минимуму, но не могу произвести MWE.

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

shared_from_this можно вызвать, только если this уже управляется другим std::shared_ptr.Поскольку вы вызываете его из конструктора J, мы можем проверить, что это не так.

со страницы shared_from_this на cppreference.com :

Разрешается вызывать shared_from_this только для ранее общего объекта, то есть для объекта, управляемого std::shared_ptr.В противном случае поведение не определено (до C ++ 17) std::bad_weak_ptr генерируется (конструктором shared_ptr из построенного по умолчанию weak_this) (начиная с C ++ 17).

Начиная с C ++ 17, ваш код будет ломаться более отчетливо.

Код

#include <memory>
#include <utility>

struct J : std::enable_shared_from_this<J>
{
    J() {
        std::ignore = shared_from_this();
    }
};

int main()
{
    std::ignore = std::make_shared<J>();
}

Компиляция и запуск

g++ -std=c++17 -Wall -Wextra -pedantic -Werror -O3 main.cpp && ./a.out

Вывод

terminate called after throwing an instance of 'std::bad_weak_ptr'
  what():  bad_weak_ptr
bash: line 7: 28216 Aborted                 (core dumped) ./a.out

До C ++ 17 ваш код имел неопределенное поведение.Я могу только догадываться, что это проявляется в случайном / странном поведении.

Могу поспорить, вы хотите что-то более простое:

#include <memory>

struct J
{
    static std::weak_ptr<J> r() { return _auto_manager; }
private:
    static std::shared_ptr<J> _auto_manager;
};
std::shared_ptr<J> J::_auto_manager = std::make_shared<J>();


int main()
{
    auto p = J::r();
}
0 голосов
/ 05 июня 2018
struct J {
  static J*& r() {
    static J* _r;
    return _r;
  }
  J() {
    r() = this;
  }
};

исправляет проблему, так как использование shared_from_this в ctor неверно.Но почему компоновщик просто пропускает var, неясно.Программа должна прерываться при запуске, но должна компилироваться и связываться.

...