Я столкнулся со сбоем среды выполнения в Visual Studio 2017 в файле minkernel\crts\ucrt\src\appcrt\string\i386\strlen.asm после изменения функции. Вот ситуация в качестве минимального примера в Compiler Explorer:
#include <string>
//void func(int i); // Original function signature
void func(const std::string& str); // New function signature: 'int' parameter changed to 'std::string'
int square(int num) {
func(0); // This implicit conversion of '0' to 'any pointer'
//func(1); // This doesn't compile anymore, which is expected
//func((void*) 0); // This doesn't compile, why?
}
версия Compiler Explorer здесь. Я попробовал несколько компиляторов и несколько версий, чтобы убедиться, что это не конкретная проблема.
Пояснения: изначально у моей функции был целочисленный параметр. Я реорганизовал его, чтобы принять параметр std::string, и использовал «Compile», чтобы компилятор нашел все вызовы и сообщил о них как об ошибках для меня; Поэтому я просмотрел каждый из них и исправил их. Например, func(1);
больше не компилируется, так как заменено на func("1");
.
Однако с вызовами func(0);
произошло нечто неожиданное: они не вызвали никаких ошибок во время компиляции, а вместо этого вылетели во время выполнения! По-видимому, в С++ все еще существует невидимое/автоматическое преобразование целочисленной константы 0 в загадочный тип указателя. Похоже, это не void *
, так как func((void*) 0);
не компилируется.
Вопрос. Есть ли способ отключить этот автоматический процесс? Или вы можете помочь мне понять, что происходит по стандарту и почему?
0
, помимо того, что является целым числом, является константой нулевого указателя. Он может быть преобразован в указатель любого типа. Если вы приведете его кconst char*
, вы получите ту же проблему: он вызывает конструкторstd::string
, который принимаетconst char*
, и передача нулевого указателя этому конструктору приводит к неопределенному поведению. - person Pete Becker   schedule 19.12.20190
. Теперь у нас естьnullptr
начиная с С++ 11. Тоже 10 лет. Странно, что однострочная программа вроде:std::string crash_global(0);
ставит на колени могучий С++. Даже с-Wall -Wextra
это ни о чем не говорит. - person Remz   schedule 20.12.2019constant 0
указателем вместо того, чтобы полагаться на типобезопасныйnullptr
, который существует со времен С++ 11? - person Remz   schedule 20.12.2019