C++通过检测标准库中的编译错误来自我毁灭

C++ destroys itself by detecting compile errors in the standard library

我无法在 Debug 配置中构建项目,因为编译器在标准库中检测到奇怪的编译错误。由于缺少Release配置,项目可以构建,但我需要以某种方式调试项目。如何修复?

示例 (<atomic>):

#ifndef _INVALID_MEMORY_ORDER
#ifdef _DEBUG
#define _INVALID_MEMORY_ORDER _STL_REPORT_ERROR("Invalid memory order")
#else // ^^^ _DEBUG / !_DEBUG vvv
#define _INVALID_MEMORY_ORDER
#endif // _DEBUG
#endif // _INVALID_MEMORY_ORDER
...
inline void _Check_memory_order(const memory_order _Order) noexcept {
    // check that _Order is a valid memory_order
    if (static_cast<unsigned int>(_Order) > static_cast<unsigned int>(memory_order_seq_cst)) {
        _INVALID_MEMORY_ORDER; // C2660 C2059 C2143
    }
}

输出:

>------ Build started: Project: CMakeLists, Configuration: Debug ------
  [1/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\input.c.obj
  [2/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\egl_context.c.obj
  [3/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\vulkan.c.obj
  [4/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\null_init.c.obj
  [5/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\init.c.obj
  [6/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\monitor.c.obj
  [7/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\osmesa_context.c.obj
  [8/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\win32_joystick.c.obj
  [9/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\context.c.obj
  [10/158] Building C object CMakeFiles\glew.dir\externals\glew\src\glew.c.obj
  [11/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\window.c.obj
  [12/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\null_monitor.c.obj
  [13/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\win32_module.c.obj
  [14/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\null_joystick.c.obj
  [15/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\win32_thread.c.obj
  [16/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\null_window.c.obj
  [17/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\platform.c.obj
  [18/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\win32_time.c.obj
  [19/158] Building RC object externals\glew\CMakeFiles\libglew_shared.dir\build\glew.rc.res
  Microsoft (R) Windows (R) Resource Compiler Version 10.0.10011.16384
  
  
  Copyright (C) Microsoft Corporation.  All rights reserved.
  
  
  
  
  [20/158] Building RC object externals\glew\CMakeFiles\libglew_static.dir\build\glew.rc.res
  Microsoft (R) Windows (R) Resource Compiler Version 10.0.10011.16384
  
  
  Copyright (C) Microsoft Corporation.  All rights reserved.
  
  
  
  
  [21/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\win32_init.c.obj
  [22/158] Linking C static library glew.lib
  [23/158] cmd.exe /C "cd /D C:\Users\maxiemar\source\repos\breakout\externals\openal-soft && "C:\Program Files\Microsoft Visual Studio22\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -D "GIT_EXECUTABLE=C:/Program Files/Git/cmd/git.exe" -D LIB_VERSION=1.21.1 -D LIB_VERSION_NUM=1,21,1,0 -D SRC=C:/Users/maxiemar/source/repos/breakout/externals/openal-soft/version.h.in -D DST=C:/Users/maxiemar/source/repos/breakout/build/vs/x64-Debug/externals/openal-soft/version.h -P C:/Users/maxiemar/source/repos/breakout/externals/openal-soft/version.cmake"
  [24/158] Building CXX object externals\openal-soft\CMakeFiles\common.dir\common\almalloc.cpp.obj
  [25/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\win32_monitor.c.obj
  [26/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\wgl_context.c.obj
  [27/158] Building C object externals\glfw\src\CMakeFiles\glfw.dir\win32_window.c.obj
  [28/158] Building CXX object externals\openal-soft\CMakeFiles\common.dir\common\alstring.cpp.obj
  [29/158] Linking C static library externals\glfw\src\glfw3.lib
  [30/158] Building CXX object externals\openal-soft\CMakeFiles\common.dir\common\ringbuffer.cpp.obj
  [31/158] Building C object externals\glew\CMakeFiles\libglew_shared.dir\src\glew.c.obj
  [32/158] Building C object externals\glew\CMakeFiles\libglew_static.dir\src\glew.c.obj
  [33/158] Building CXX object externals\openal-soft\CMakeFiles\common.dir\common\polyphase_resampler.cpp.obj
  [34/158] Linking C static library externals\glew\lib\glewd.lib
  [35/158] Building CXX object externals\openal-soft\CMakeFiles\common.dir\common\alcomplex.cpp.obj
  [36/158] Linking C shared library externals\glew\bin\glew-sharedd.dll
  [37/158] Building CXX object externals\openal-soft\CMakeFiles\common.dir\common\alfstream.cpp.obj
  [38/158] Building CXX object externals\openal-soft\CMakeFiles\common.dir\common\dynload.cpp.obj
  [39/158] Building CXX object externals\openal-soft\CMakeFiles\common.dir\common\threads.cpp.obj
  [40/158] Building CXX object externals\openal-soft\CMakeFiles\common.dir\common\strutils.cpp.obj
  [41/158] Linking CXX static library externals\openal-soft\common.lib
  [42/158] Generating hrtf_default.h
  [43/158] Building CXX object CMakeFiles\breakout.dir\src\graphics\Texture.cpp.obj
  [44/158] Building CXX object CMakeFiles\breakout.dir\src\input\InputManager.cpp.obj
  [45/158] Building CXX object CMakeFiles\breakout.dir\src\graphics\Shader.cpp.obj
  [46/158] Building CXX object CMakeFiles\breakout.dir\src\utils\FileManager.cpp.obj
  FAILED: CMakeFiles/breakout.dir/src/utils/FileManager.cpp.obj 
  C:\PROGRA~1\MICROS~422\COMMUN~1\VC\Tools\MSVC30~1.307\bin\Hostx64\x64\cl.exe  /nologo /TP -DGLEW_STATIC -IC:\Users\maxiemar\source\repos\breakout\externals\glew\include -IC:\Users\maxiemar\source\repos\breakout\externals\openal-soft\include -IC:\Users\maxiemar\source\repos\breakout\externals\glm -IC:\Users\maxiemar\source\repos\breakout\externals\stb -IC:\Users\maxiemar\source\repos\breakout\externals\glfw\include -IC:\Users\maxiemar\source\repos\breakout\externals\openal-soft\include\AL /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1 -std:c++17 /showIncludes /FoCMakeFiles\breakout.dir\src\utils\FileManager.cpp.obj /FdCMakeFiles\breakout.dir\ /FS -c C:\Users\maxiemar\source\repos\breakout\src\utils\FileManager.cpp
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(206): error C2143: syntax error: missing ')' before 'string'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(206): error C2660: '_invalid_parameter': function does not take 2 arguments
  C:\Program Files (x86)\Windows Kits\include.0.19041.0\ucrt\corecrt.h(348): note: see declaration of '_invalid_parameter'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(206): error C2143: syntax error: missing ';' before 'string'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(206): error C2059: syntax error: ')'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(221): error C2143: syntax error: missing ')' before 'string'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(221): error C2660: '_invalid_parameter': function does not take 2 arguments
  C:\Program Files (x86)\Windows Kits\include.0.19041.0\ucrt\corecrt.h(348): note: see declaration of '_invalid_parameter'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(221): error C2143: syntax error: missing ';' before 'string'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(221): error C2059: syntax error: ')'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(237): error C2143: syntax error: missing ')' before 'string'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(237): error C2660: '_invalid_parameter': function does not take 2 arguments
  C:\Program Files (x86)\Windows Kits\include.0.19041.0\ucrt\corecrt.h(348): note: see declaration of '_invalid_parameter'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(237): error C2143: syntax error: missing ';' before 'string'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(237): error C2059: syntax error: ')'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(297): error C2143: syntax error: missing ')' before 'string'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(297): error C2660: '_invalid_parameter': function does not take 2 arguments
  C:\Program Files (x86)\Windows Kits\include.0.19041.0\ucrt\corecrt.h(348): note: see declaration of '_invalid_parameter'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(297): error C2143: syntax error: missing ';' before 'string'
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.30.30705\include\atomic(297): error C2059: syntax error: ')'
  [47/158] Building CXX object CMakeFiles\breakout.dir\src\Window.cpp.obj
  [48/158] Building CXX object CMakeFiles\breakout.dir\src\graphics\SpriteRenderer.cpp.obj
  [49/158] Building CXX object CMakeFiles\breakout.dir\src\ResourceManager.cpp.obj
  [50/158] Building CXX object CMakeFiles\breakout.dir\src\game\GameObject.cpp.obj
  [51/158] Building CXX object CMakeFiles\breakout.dir\src\graphics\ShaderProgram.cpp.obj
  [52/158] Building CXX object CMakeFiles\breakout.dir\src\game\GameLevel.cpp.obj
  [53/158] Building CXX object CMakeFiles\breakout.dir\src\Game.cpp.obj
C:\Users\maxiemar\source\repos\breakout\src\graphics\Font.h(6): warning C5208: unnamed class used in typedef name cannot declare members other than non-static data members, member enumerations, or member classes
C:\Users\maxiemar\source\repos\breakout\src\Game.cpp(65): warning C4267: '=': conversion from 'size_t' to 'GLint', possible loss of data
C:\Users\maxiemar\source\repos\breakout\src\Game.cpp(68): warning C4267: '=': conversion from 'size_t' to 'GLint', possible loss of data
  [54/158] Building CXX object CMakeFiles\breakout.dir\src\game\Brick.cpp.obj
  [55/158] Building CXX object CMakeFiles\breakout.dir\src\game\Ball.cpp.obj
  ninja: build stopped: subcommand failed.

CMakeLists.txt:

cmake_minimum_required(VERSION 3.8)
project(breakout)

find_package(OpenGL REQUIRED)

set(CMAKE_CXX_STANDARD 17)

set(SOURCES src/main.cpp src/WindowManager.cpp src/WindowManager.h src/Window.cpp src/Window.h src/graphics/Shader.cpp src/graphics/Shader.h src/graphics/ShaderType.h src/graphics/ShaderProgram.cpp src/graphics/ShaderProgram.h src/utils/FileManager.cpp src/utils/FileManager.h src/graphics/Texture.cpp src/graphics/Texture.h src/ResourceManager.cpp src/ResourceManager.h src/input/InputManager.cpp src/input/InputManager.h src/input/EventHandlers.h src/Game.cpp src/Game.h src/game/GameState.h src/graphics/SpriteRenderer.cpp src/graphics/SpriteRenderer.h src/Singleton.h src/game/GameObject.cpp src/game/GameObject.h src/game/Brick.cpp src/game/Brick.h src/game/GameLevel.cpp src/game/GameLevel.h src/game/Player.cpp src/game/Player.h src/game/Ball.cpp src/game/Ball.h src/physics/Direction.h src/physics/Collision.h src/physics/CollisionDetector.cpp src/physics/CollisionDetector.h src/graphics/Particle.h src/graphics/ParticleEmitter.cpp src/graphics/ParticleEmitter.h src/graphics/PostProcessor.cpp src/graphics/PostProcessor.h src/graphics/PostProcessingEffect.h src/game/PowerUp.cpp src/game/PowerUp.h src/game/PowerUpType.h src/utils/Random.cpp src/utils/Random.h src/audio/AudioManager.h src/audio/AudioManager.cpp src/audio/AudioFile.h src/graphics/TextRenderer.h src/graphics/TextRenderer.cpp src/graphics/Font.h src/graphics/GlyphInfo.h src/AssetsLoader.cpp src/AssetsLoader.h)

# GLFW build configuration

set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)

add_subdirectory(externals/glfw)

# end
# ------------------------
# GLEW build configuration

add_subdirectory(externals/glew)
include_directories(externals/glew/include)
add_library(glew STATIC externals/glew/src/glew.c)
add_definitions(-DGLEW_STATIC)

# end
# ------------------------
# OpenAL build configuration

add_subdirectory(externals/openal-soft)
include_directories(externals/openal-soft/include)

# end
# ------------------------
# Header-only libraries

include_directories(externals/glm)
include_directories(externals/stb)

# end

add_executable(breakout ${SOURCES})

target_link_libraries(breakout glfw glew OpenAL ${OPENGL_LIBRARY})

更新

一般来说,我找不到任何可能导致此类错误的东西。

FileManager.h:

#pragma once

#include "../audio/AudioFile.h"
#include <GL/glew.h>
#include <string>
#include <vector>

class FileManager {
public:
    static std::string readAsText(const std::string& path);
    static std::vector<unsigned char> readAsBinary(const std::string& path);
    static unsigned char* readImage(const std::string& path,
                                    GLint width,
                                    GLint height,
                                    GLint components,
                                    bool flip = false);
    static AudioFile readOggFile(const std::string& path);
};

AudioFile.h:

#pragma once

#include <memory>

struct AudioFile {
    int channels;
    int sampleRate;
    int samples;
    std::unique_ptr<short> data;

    int getSampleCount() const {
        return channels * samples;
    }
};

FileManager.cpp:

#include "FileManager.h"
// STB_IMAGE_IMPLEMENTATION must be defined in *.c or *.cpp file (not in header)
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <stb_vorbis.c>
#include <iostream>
#include <fstream>
#include <sstream>

std::string FileManager::readAsText(const std::string &path) {
    std::string content = "";
    std::ifstream file(path);

    if (file.is_open()) {
        std::stringstream stream;
        // Read file's buffer contents into stream
        stream << file.rdbuf();
        file.close();
        // Convert stream into string
        content = stream.str();
    } else {
        std::cerr << "Unable to open text file " << path << std::endl;
    }

    return content;
}

std::vector<unsigned char> FileManager::readAsBinary(const std::string& path) {
    std::ifstream file(path, std::ios::binary | std::ios::ate);

    if (!file.is_open()) {
        std::cerr << "Unable to open font file " << path << std::endl;
    }

    auto size = file.tellg();
    auto bytes = std::vector<unsigned char>(size);
    file.seekg(0, std::ios::beg);
    file.read(reinterpret_cast<char*>(&bytes.front()), size);
    file.close();

    return bytes;
}

unsigned char* FileManager::readImage(const std::string& path,
                                      GLint width,
                                      GLint height,
                                      GLint channels,
                                      bool flip) {
    stbi_set_flip_vertically_on_load(flip);
    auto image = stbi_load(path.c_str(), &width, &height, &channels, 0);
    if (image == nullptr) {
        std::cerr << "Unable to open image file " << path << std::endl
                  << "Reason: " << stbi_failure_reason() << std::endl;
    }

    return image;
}

AudioFile FileManager::readOggFile(const std::string& path) {
    AudioFile audioFile;
    short* output;
    audioFile.samples = stb_vorbis_decode_filename(path.c_str(),
                                                   &audioFile.channels,
                                                   &audioFile.sampleRate,
                                                   &output);
    audioFile.data = std::unique_ptr<short>(output);

    return audioFile;
}

确实是stb_vorbis.c文件的问题,#define与标准库冲突。我通过从 stb 中隔离然后转到此文件发现了这一点。

我受到解决方案 here 的启发。 以 stb_vorbis.c 位于列表末尾的方式重新排列 #include 指令对我来说很合适。现在可以完整地构建整个项目了。

FileManager.cpp:

#include "FileManager.h"

#include <iostream>
#include <fstream>
#include <sstream>

// STB_IMAGE_IMPLEMENTATION must be defined in *.c or *.cpp file (not in header)
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

#define STB_VORBIS_HEADER_ONLY
#include <stb_vorbis.c>
#undef STB_VORBIS_HEADER_ONLY