Search code examples
c++c++11gccmsvc12

Why exception can not be caught on windows by msvc but on Linux by GCC


The same files on Windows and Linux as follow:

std_exp.cpp

#include <iostream>
#include <string>
#include <stdexcept>

using namespace std;

int main() {
    try {
        std::string s{nullptr};
    } catch (const std::exception &e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
    }

    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(test001)
set(CMAKE_CXX_STANDARD 11)
message(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "C++ compiler ID: ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "C++ compiler version: ${CMAKE_CXX_COMPILER_VERSION}")
add_executable(test001 std_exp.cpp)

This is my compile commands. comile commands

cmake -B ./build -S ./
cmake --build ./build/ --config Release

compiler output

On Windows:
-- Selecting Windows SDK version 10.0.22621.0 to target Windows 10.0.22000.
-- C++ compiler: ${ROOT_PATH1}/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.40.33807/bin/Hostx64/x64/cl.exe
-- C++ compiler ID: MSVC
-- C++ compiler version: 19.40.33812.0
-- Configuring done
-- Generating done
-- Build files have been written to: ${ROOT_PATH2}/build

On Linux:
-- C++ compiler: /usr/bin/c++
-- C++ compiler ID: GNU
-- C++ compiler version: 11.4.0
-- Configuring done
-- Generating done
-- Build files have been written to: ${ROOT_PATH3}/build

The executable output on Linux

On Windows:
(no output)
On Linux:
std_exp.cpp15Caught exception: basic_string: construction from null is not valid

So why exp can not be caught on windows?


Solution

  • The constructor of std::string that you are trying to use has undefined behavior if the argument isn't actually a pointer to a string. See https://en.cppreference.com/w/cpp/string/basic_string/basic_string, specifically overload (9).

    That one compiler happens to throw an exception while the other doesn't is completely reasonable outcome under undefined behavior, as is any other behavior at all.

    As a side note: Starting with C++23 there is an extra overload (18) that will make a call with nullptr as argument to the constructor of std::string ill-formed.