将编译时常量向量转换为堆分配的版本

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

[我使Visual Studio的代码分析器发疯。这行:

void Foo() {
    const std::vector<uint8_t> bar{ /* 21,140 uint8_t entries */ };
    //...
}

发出C6262 warning

Function uses 21140 bytes of stack: exceeds /analyze:stacksize`16384`. Consider moving some data to heap

向量包含二进制文件的各个字节。在这种情况下,我的全部意图是不使用外部文件,因此数据始终可供函数调用者使用。

是否有一种简单的方法可以将编译时值转换为堆分配的值?

将声明从函数中移出到静态文件级范围是非常昂贵和耗时的,因为A)永远不会释放内存,并且B)这只是使用多个大型二进制数组的十几个函数之一像这样并重命名它们都无法很好地扩展。

忽略警告也是不可能的。

编辑:

根据要求获得MCRE。 (“ CR”是值得商because的,因为它是300,000 LOC游戏引擎的一部分,但这无关紧要,因为CA在出现太大矢量的基本声明时失败了,所以这里是实际用法。) ShadowRanger's answer的注释,既没有将大向量声明为static,也没有将const static声明解决此问题,并且CA仍然发出警告:

std::unique_ptr<ShaderProgram> Renderer::CreateDefaultShaderProgram() noexcept {
    static std::vector<uint8_t> g_VertexFunction{ /* 5K entries */ };
    static std::vector<uint8_t> g_DefaultPixelFunction{ /* 21,140 entries */ };
    // /\/\ Code Analysis warns here at g_DefaultPixelFunction declaration.

    ShaderProgramDesc desc{};
    desc.name = "__default";
    desc.device = _rhi_device.get();
    {
        ID3D11VertexShader* vs = nullptr;
        _rhi_device->GetDxDevice()->CreateVertexShader(g_VertexFunction.data(), g_VertexFunction.size(), nullptr, &vs);

        ID3DBlob* blob = nullptr;
        ::D3DCreateBlob(g_VertexFunction.size(), &blob);
        std::memcpy(blob->GetBufferPointer(), g_VertexFunction.data(), g_VertexFunction.size());

        g_VertexFunction.clear();
        g_VertexFunction.shrink_to_fit();

        desc.vs = vs;
        desc.vs_bytecode = blob;
        desc.input_layout = _rhi_device->CreateInputLayoutFromByteCode(blob);
    }
    {
        ID3D11PixelShader* ps = nullptr;
        _rhi_device->GetDxDevice()->CreatePixelShader(g_DefaultPixelFunction.data(), g_DefaultPixelFunction.size(), nullptr, &ps);

        ID3DBlob* blob = nullptr;
        ::D3DCreateBlob(g_DefaultPixelFunction.size(), &blob);
        std::memcpy(blob->GetBufferPointer(), g_DefaultPixelFunction.data(), g_DefaultPixelFunction.size());

        g_DefaultPixelFunction.clear();
        g_DefaultPixelFunction.shrink_to_fit();

        desc.ps = ps;
        desc.ps_bytecode = blob;
    }
    return std::make_unique<ShaderProgram>(std::move(desc));
}

编辑2:

根据(Jeff Garrett的回答)[https://stackoverflow.com/a/62207299/421178],解决方案是事先将初始化列表变量声明为静态(const因为“ Const all Things”!

const static std::initializer_list<uint8_t> vs_init_list{/*5K entries*/};
std::vector<uint8_t> g_VertexFunction{vs_init_list};

const static std::initializer_list<uint8_t> ps_init_list{/*21K entries*/};
std::vector<uint8_t> g_PixelFunction{ps_init_list};

//... Same as before

[我使Visual Studio的代码分析器发疯。这行代码:void Foo(){const std :: vector bar {/ * 21,140 uint8_t entry * /}; // ...}发出C6262警告:函数使用21140 ...

c++ c++17 heap visual-studio-2019
3个回答
1
投票

向量的堆栈空间不取决于其大小。


3
投票

[如果将它们保留在原处并声明为staticconst,则不需要重命名; static不需要移至文件范围(这可能会导致名称冲突),仅在需要在多个功能之间共享时才移至文件范围。


2
投票

看看是否有帮助。它不会将数据移到堆中,但会将其放入静态数据中,而该数据根本不需要运行时即可初始化。

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