boost-ext / di

C++14 Dependency Injection Library
https://boost-ext.github.io/di
1.16k stars 140 forks source link

Segfault when using named injection with runtime_injector #398

Open ColinDuquesnoy opened 5 years ago

ColinDuquesnoy commented 5 years ago

Context

I am trying to use the runtime_injector (because our application with hundreds of bindings now takes several minutes to compile and compilation time looks exponential :worried: ). We're using named injection and shared_factory extension extensively in our application (because of #252).

Unfortunately it looks like using named injection or shared_factory does not work with the runtime_injector. This issue is about named injection (I'll create another one for the usage of shared_factory).

Please let me know if this is a known limitation or if I am using it wrong.

Sample code

#include <boost/di.hpp>
#include <boost/di/extension/providers/runtime_provider.hpp>
#include <iostream>

namespace di = boost::di;
namespace ext = di::extension;

class ILoggerFactory
{
public:
    virtual ~ILoggerFactory() = default;
    virtual std::shared_ptr<int> create() = 0;
};

class LoggerFactory: public ILoggerFactory
{
public:
    std::shared_ptr<int> create() override
    {
        std::cout << "LoggerFactory::create()" << std::endl;
        return std::make_shared<int>(42);
    }
};

auto basicLoggerFactory = []{};

class CachedLoggerFactory : public ILoggerFactory
{
public:
    BOOST_DI_INJECT(explicit CachedLoggerFactory, (named = basicLoggerFactory) ILoggerFactory& decorated) : _decorated(decorated)
    {

    }

    std::shared_ptr<int> create() override
    {
        std::cout << "CachedLoggerFactory::create()" << std::endl;
        return _decorated.create();
    }

private:
    ILoggerFactory& _decorated;
};

class Program
{
public:
    explicit Program(ILoggerFactory& loggerFactory) : _loggerFactory(loggerFactory)
    {

    }

    int Run()
    {
        return *_loggerFactory.create();
    }

private:
    ILoggerFactory& _loggerFactory;
};

int main()
{
    //auto injector = di::make_injector(
    ext::runtime_injector injector;
    injector.install(
            di::bind<ILoggerFactory>.named(basicLoggerFactory).to<LoggerFactory>(),
            di::bind<ILoggerFactory>.to<CachedLoggerFactory>()
    );

    auto& program = injector.create<Program&>();
    return program.Run();
}

Expected Behavior

I expect the following output (which I get if don't use the runtime_injector):

/home/cdu/CLionProjects/poc-boost-di-runtime-injector/cmake-build-debug/main
CachedLoggerFactory::create()
LoggerFactory::create()

Process finished with exit code 0

Actual Behavior

The program crashes:

/home/cdu/CLionProjects/poc-boost-di-runtime-injector/cmake-build-debug/main

Process finished with exit code 11

Steps to Reproduce the Problem

  1. Compile the sample code
  2. Run the program
  3. The program crashes

Specifications