C ++动态库和带有调试符号的std :: unique_ptr破坏堆栈

问题描述 投票:0回答:1

我制作了一个存储库,其中包含我在项目中遇到的问题的简化版本:https://github.com/michalPietraszko/Test

PS。我对premake不太熟悉,因此您需要两次构建该项目才能使其正常工作

简而言之,当我使用sybmols构建项目时,出现调试断言失败:

调试断言失败!

程序:... Tst \ Test \ Client .. \ bin \ Debug-windows-x86_64 \ Client \ Client.exe文件:minkernel \ crts \ ucrt \ src \ appcrt \ heap \ debug_heap.cpp线:996

表达式:__acrt_first_block ==标头

关闭sybmol后运行良好。

我有2个问题:

  • 我的方法是否正确?
  • 为什么它仅在调试配置时失败?

谢谢你!!!

库代码:

#include <memory>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>

#ifdef BUILD_DLL
    #define API __declspec(dllexport)
#else
    #define API __declspec(dllimport)
#endif

namespace lib
{
    class API Event
    {
    public:
        std::string toString() const { std::stringstream ss; ss<<"example str"; return ss.str(); }
        const char* getName() const { return "example char"; }
    };

    class API Layer
    {
    public:
        virtual void onEvent(Event&) {}
    };

    class API Application
    {
    public:
        Application() = default;
        Application(const Application&) = delete;
        Application(Application&&) = default;
        Application& operator=(Application&&) = default;
        Application& operator=(const Application&) = delete;
        ~Application() = default;

        template<typename T>
        void pushLayer()
        {
            vec.push_back(std::make_unique<T>());
        }

        void run()
        {   
            bool doneOnce{ false };
            while (true) 
            {
                if (!doneOnce) 
                {
                    Event e{};
                    (*vec.begin())->onEvent(e);
                    doneOnce = true;
                }
            }
        }

        std::vector<std::unique_ptr<Layer>> vec;
    };

    Application* createApplication(); // define in client
}// namespace

客户代码:

#include <Main.hpp>

class Example : public lib::Layer
{
public:
    void onEvent(lib::Event& e) override
    {
        std::cout << "On Event" << std::endl;

        std::string s = e.toString(); // crashes application upon exiting the scope
        std::cout << s << std::endl; 

        //std::cout << e.toString() << std::endl; // crashes after this line

        //e.getName(); // returns const char*, works fine

        std::cout << "I did run ok" << std::endl;
    }
};

extern lib::Application* lib::createApplication();

class Client : public lib::Application
{
public:
    Client() { pushLayer<Example>(); }
};

lib::Application* lib::createApplication()
{
    return new Client();
}

int main(int argc, char** argv)
{
    auto app = lib::createApplication();
    app->run();
    delete app;
}

预制文件:

--pramake.lua

workspace "Test"
    architecture "x64"

    configurations
    {
        "Debug",
        "Release"
    }

outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"

--include "Luna/vendor/GLFW"
startproject "Client"

project "DynLib"
    location "DynLib"
    kind "SharedLib"
    language "C++"

    targetdir("bin/" .. outputdir .. "/%{prj.name}")
    objdir("bin-int/" .. outputdir .. "/%{prj.name}")

--    pchheader "lnpch.h"
--    pchsource "Luna/src/lnpch.cpp"

    files
    {
        "%{prj.name}/**.hpp",
        "%{prj.name}/**.cpp"
    }

    includedirs
    {
        "%{prj.name}/"
    } 

    filter "system:windows"
        cppdialect "C++17"
        staticruntime "On"
        systemversion "latest"

        defines
        {
            "BUILD_DLL"
        }

        postbuildcommands
        {
            ("{COPY} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Client")
        }

    filter "configurations:Debug"
        symbols "On"

    filter "configurations:Release"
        symbols "Off"

project "Client"
    location "Client"
    kind "ConsoleApp"    
    language "C++"

    targetdir("bin/" .. outputdir .. "/%{prj.name}")
    objdir("bin-int/" .. outputdir .. "/%{prj.name}")

    files
    {
        "%{prj.name}/**.hpp",
        "%{prj.name}/**.cpp"
    }

    includedirs
    {
        "DynLib/"
    }

    links
    {
        "DynLib"
    }

    filter "system:windows"
        cppdialect "C++17"
        staticruntime "On"
        systemversion "latest"

        defines
        {
            "LN_PLATFORM_WINDOWS",
        }

    filter "configurations:Debug"
        symbols "On"

    filter "configurations:Release"
        symbols "Off"
c++ dll stl crash stack
1个回答
0
投票

[您同时使用了LayerApplication,但是没有给它们提供虚拟析构函数。

[由std::unique_ptr<Layer>构造的std::make_shared<Example>被破坏时,您将具有不确定的行为,因为它在delete指针上调用Layer*,试图通过Example指针删除Layer对象。如果基类没有虚拟析构函数,则将导致未定义的行为。

[类似地,在delete app;中,app的类型为Application*,但是它指向的对象的动态类型为派生类型Client。再次通过基类指针删除动态类型的对象会导致未定义的行为,而基类没有虚拟析构函数。

添加

virtual ~Layer() = default;

virtual ~Application() = default;

到您的两个基类。

© www.soinside.com 2019 - 2024. All rights reserved.