Search code examples
c++boostdllshared-librariesdllimport

Program crashes when the destructor of an std::fstream object that was passed to a shared library function


I have a shared library.

A function is declared in it, which takes a functor as a parameter. This functor returns an object of type std::fstream.

In the body of the function, the functor is called and data is written to the received stream, after which the function finishes.

However, as I saw in the debugger, during the call of the destructor of the std::fstream object an error occurs, causing the program to crash. This error occurs only when compiling under Windows.

This destructor error does not occur if the std::fstream object is not created explicitly in a dynamic library function, but rather with the passed functor.

A minimal reproducible example is below:

lib.cpp

#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION
#include <fstream>
#include <function>
#include <boost/dll/alias.hpp>

void BOOST_SYMBOL_VISIBLE func (std::function<std::fstream()> file_generator) {
    auto file = file_generator();
    file << "test" << std::endl;
}

BOOST_DLL_ALIAS( func, plugin)

This function receives a functor that returns an object of type std::fstream and writes plain text to the resulting file.

CMake file to compile the shared library

cmake_minimum_required(VERSION 3.16)
project(lib)

set(CMAKE_CXX_STANDARD 20)


add_library(lib SHARED lib.cpp)
set(CMAKE_SHARED_LINKER_FLAGS "-static")

main.cpp

#include <boost/dll.hpp>
#include <fstream>
#include <function>

typedef void (create_t)(std::function<std::fstream()>);

int main() {
    auto func = boost::dll::import_alias<create_t>("lib.dll", plugin);
    func([](){ return std::fstream("file.txt", std::ios::out);});
}

CMake file to compile the main program:

cmake_minimum_required(VERSION 3.16)
project(TestingCore)

set(CMAKE_CXX_STANDARD 20)
add_executable(TestingCore main.cpp)
set(CMAKE_EXE_LINKER_FLAGS "-static")

In this case the file is created correctly and the text is written to it correctly, the program crashes on the stream destructor.


Solution

  • When the object is created and used within the function passed as a functor, it is likely that its destructor is called within the same scope and memory space as where it was created. However, when the object is created explicitly within the shared library function, it may be destroyed in a different scope or memory space than where it was created, leading to memory access errors and program crashes.

    The only more or less convenient solution I have found so far is to change the logic of the program a bit.

    The std::fstream object itself should be created within a dynamic library function, and the file should be opened using the passed functor.

    void BOOST_SYMBOL_VISIBLE func (std::function<void(std::fstream&)> file_generator) {
        std::fstream file;
        file_generator(file);
        file << "test" << std::endl;
    }
    
    
    typedef void (create_t)(std::function<void(std::fstream&)>);
    
    int main() {
        auto func = boost::dll::import_alias<create_t>("lib.dll", plugin);
        func([](std::fstream& file){ file.open("file.txt", std::ios::out);});
    }