Те же файлы в Windows и Linux:
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)
Это мои команды компиляции. компилировать команды
cmake -B ./build -S ./
cmake --build ./build/ --config Release
вывод компилятора
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
Исполняемый вывод в Linux
On Windows:
(no output)
On Linux:
std_exp.cpp15Caught exception: basic_string: construction from null is not valid
Так почему же эксп не ловится на винде?
Конструктор std::string
, который вы пытаетесь использовать, имеет неопределенное поведение, если аргумент на самом деле не является указателем на строку. См. https://en.cppreference.com/w/cpp/string/basic_string/basic_string, в частности перегрузку (9).
Тот факт, что один компилятор выдает исключение, а другой нет, является вполне разумным результатом при неопределенном поведении, как и любое другое поведение вообще.
В качестве примечания: начиная с C++23 существует дополнительная перегрузка (18), которая будет вызывать nullptr
в качестве аргумента конструктора std::string
неправильного формата.
В документации cppreference фактически упоминается случай использования нулевого указателя для создания std::string
в качестве конкретного примера возникновения неопределенного поведения:
Basic_string( const CharT* s, const Allocator& alloc = Allocator() ); (9)
(9) ...
Поведение не определено, если [s, s + Traits::length(s)) не является допустимым. диапазон (например, если s — нулевой указатель).
(выделено мной)
Это именно то, что вы делаете, и, следовательно, это UB (неопределённое поведение), и каждый результат действителен.
В частности, каждый компилятор волен обрабатывать его по своему усмотрению (включая создание исключения или любой другой способ обработки).
cppreference — хороший справочник, но, по моему мнению, называть его «документацией» вводит в заблуждение.
@ 463035818_is_not_an_ai, насколько я понимаю, помимо самого стандарта, считается, что cppreference предлагает лучшую документацию для C++ (именно это я имел в виду). Но в любом случае я обновил и явно упомянул cppreference, чтобы избежать путаницы.
@ 463035818_is_not_an_ai Это лучший источник информации о C++, который все еще доступен для чтения большинству пользователей (стандарт C++, хотя и более корректен, не так читабелен, и ему определенно не хватает канонических примеров, которые есть в cppreference). Так что да, я бы тоже посчитал это де-факто документацией для практического использования.
@PepjinKramer «де-факто» все еще не является «документацией». Говоря, что это «документация», подразумевается, что она будет единственной/официальной, чего на самом деле нет. Немного неправильно — это все равно неправильно, и, по моему мнению, это заслуживает лучшего, называть это правильным именем уже достаточно хорошо. Это лучший справочный сайт, который я знаю.
@PepijnKramer Я действительно согласен с 463035818_is_not_an_ai в том, что «документация» подразумевает официальную, поэтому я отредактировал, указав явно cpprefernce. Но мы все согласны, что это лучший справочник на данный момент.
Смотрите обман: Что происходит, когда я инициализирую std::string значением 0?