头文件破坏了一个程序,但在另一个程序中有效

问题描述

我有以下头文件-

#pragma once
#include <vector>

template<int rows,int cols = rows>
class mat {
public:
    mat() : values{ rows,std::vector<double>(cols) } {
        if (rows == cols) {
            int y = 0;
            for (int x = 0; x < rows; x++) {
                values[x][y] = 1;
                y++;
            }
        }
    }
    mat(int val) : values{ rows,std::vector<double>(cols,val) } {}
    std::vector<double> &operator[](int x) {
        return values[x];
    }
private:
    std::vector<std::vector<double>> values;
};

当我单独编译它时,与我的大项目分开,它工作正常。但是,当我将它与我的项目一起编译时,我在运行时收到错误 Invalid address specified to RtlValidateHeap( 000001CBA8F80000,000001CBA8F99BC0 )。即使我根本不引用头文件,我也会收到此错误!只是纯粹编译我的项目中的头文件,即使它从未以任何方式被引用,也会给我一个运行时错误。这个错误似乎在 main 被调用之前就发生了。我不能在 main 中设置断点来调试它,或者在类的构造函数中设置断点来调试它。我什至不能std::cout 程序中的任何内容。据我所知,它甚至没有进入主程序。我已经尝试了我能想到的一切。我在 msvc 中使用 CMake。但令人震惊的是,当我将完全相同的头文件放入演示程序时,它运行良好!一切都按预期工作。如果你认为你需要它,这是我的 CMakeLists.txt 文件-

cmake_minimum_required (VERSION 3.8)

add_executable(physics WIN32 "main.cpp" "mat.h" "vec2.h"  "poly_flags.h" "poly.h" "poly.cpp" "object.h" "object.cpp" "world.h" "world.cpp")

target_include_directories(physics PRIVATE "${CMAKE_SOURCE_DIR}/include")

target_compile_deFinitions(physics PRIVATE "$<$<CONfig:Debug>:" "_DEBUG" ">" "$<$<CONfig:Release>:" "NDEBUG" ">" "WIN32;" "_CONSOLE;" "UNICODE;" "_UNICODE")
target_compile_options(physics PRIVATE /Oi; /Gy; /permissive-; /sdl; /W2; /doc; $<$<CONfig:Debug>:/Z7>; ${DEFAULT_CXX_DEBUG_informatION_FORMAT}; ${DEFAULT_CXX_EXCEPTION_HANDLING})

target_link_options(physics PRIVATE $<$<CONfig:Debug>: /INCREMENTAL; /NODEFAULTLIB:LIBCMTD; /NODEFAULTLIB:MSVCRT> $<$<CONfig:Release>: /DEBUG:FULL /OPT:REF; /OPT:ICF; /INCREMENTAL:NO> /NODEFAULTLIB:LIBCMT)

target_link_libraries(physics PRIVATE SDL2main SDL2 winmm version Imm32 Setupapi libcmt libucrtd)

target_link_directories(physics PRIVATE "${CMAKE_SOURCE_DIR}/lib")

这是我引用它的 main.cpp 文件-

mat<5> mat5;

for (int y = 0; y < 5; y++) {
    for (int x = 0; x < 5; x++) {
        std::cout << mat5[x][y] << ",";
    }
    std::cout << std::endl;
}

我会留下一些代码,但我向您保证,该代码不会以任何方式影响它。除了一些晦涩的编译器错误之外,我想不出任何原因会发生这种情况。显然,这门课还远未完成,但过去几天我一直在尝试调试它。您可能会认为我在程序中的其他地方分配内存而没有正确删除它,或者删除它两次(因为这通常是运行时错误的意思),但我只对所有容器使用 std::vector .我的意思是除了另一个文件中的地图。

Here's github repo 如果您想亲自尝试一下。老实说,您很可能会编译它并且一切正常。或者同样有可能这是一些明显的错误。注意:main.cpp 第 30 行之后的任何内容都无关紧要,其中大部分内容可能没有意义。我确信应用程序的其他部分存在无数错误,如果没有“mat.h”文件,它甚至无法工作。我的意思是它可以编译,但还没有运行。无论如何,提前感谢您的帮助,我真的可以使用它!

由于反对票 - 这是我得到的调用堆栈 -

>   ntdll.dll!RtlpBreakPointHeap()  UnkNown
    ntdll.dll!RtlpValidateHeapEntry()   UnkNown
    ntdll.dll!RtlValidateHeap() UnkNown
    KernelBase.dll!HeapValidate()   UnkNown
    physics.exe!_CrtIsValidHeapPointer(const void * block) Line 1407    C++
    physics.exe!free_dbg_nolock(void * const block,const int block_use) Line 904   C++
    physics.exe!_free_dbg(void * block,int block_use) Line 1030    C++
    physics.exe!__acrt_free_locale(__crt_locale_data * ptLoci) Line 183 C++
    physics.exe!_updatetLocinfoEx_nolock(__crt_locale_data * * pptLocid,__crt_locale_data * ptLocis) Line 240  C++
    physics.exe!_wsetlocale::__l2::void <lambda>(void)::__l5::<lambda>() Line 518   C++
    physics.exe!__crt_seh_guarded_call<void>::operator()<void <lambda>(void),void <lambda>(void) &,void <lambda>(void)>(__acrt_lock_and_call::__l2::void <lambda>(void) && setup,_wsetlocale::__l2::void <lambda>(void)::__l5::void <lambda>(void) & action,__acrt_lock_and_call::__l2::void <lambda>(void) && cleanup) Line 224  C++
    physics.exe!__acrt_lock_and_call<void <lambda>(void)>(const __acrt_lock_id lock_id,_wsetlocale::__l2::void <lambda>(void)::__l5::void <lambda>(void) && action) Line 980   C++
    physics.exe!_wsetlocale::__l2::<lambda>() Line 528  C++
    physics.exe!__crt_seh_guarded_call<void>::operator()<void <lambda>(void),void <lambda>(void) &>(__crt_call_and_cleanup::__l2::void <lambda>(void) && setup,_wsetlocale::__l2::void <lambda>(void) & action,_wsetlocale::__l2::void <lambda>(void) & cleanup) Line 224   C++
    physics.exe!__crt_call_and_cleanup<void <lambda>(void),void <lambda>(void)>(_wsetlocale::__l2::void <lambda>(void) && action,_wsetlocale::__l2::void <lambda>(void) && cleanup) Line 238   C++
    physics.exe!_wsetlocale(int _category,const wchar_t * _wlocale) Line 531   C++
    [Inline Frame] physics.exe!call_wsetlocale(const int category,const char * const narrow_locale) Line 30    C++
    physics.exe!setlocale::__l2::<lambda>() Line 41 C++
    physics.exe!__crt_seh_guarded_call<char *>::operator()<void <lambda>(void),char * <lambda>(void) &,setlocale::__l2::char * <lambda>(void) & action,__acrt_lock_and_call::__l2::void <lambda>(void) && cleanup) Line 204 C++
    [Inline Frame] physics.exe!__acrt_lock_and_call(const __acrt_lock_id) Line 976  C++
    physics.exe!setlocale(int _category,const char * _locale) Line 118 C++
    [External Code] 
    physics.exe!_initterm(void(*)() * first,void(*)() * last) Line 22  C++

解决方法

解决方案相当简单。我使用的是静态 C 运行时库,因为我认为您在静态链接 SDL2 时需要这样做。事实是您需要将 /MD 用于多线程 DLL 始终与 SDL2 一起使用。