Ошибка исключения xstring при обнулении структуры

Помогите пожалуйста понять в чем ошибка ? :(

Причем ошибка с которой я первый раз встречаюсь - сам код компилируется, но завершается ошибкой. Попытка запустить его в дебаг режиме, приводит к том, что отладка даже на первую строку не встает, а сразу переходить в файл xstring c ошибкой:

return __builtin_strlen(_First);

Вызвано исключение по адресу 0x00007FF607A36C14: 0xC0000005: нарушение прав доступа при чтении по адресу 0x0000000000000000.

Проблема явно в этой строчке кода: my_struct_class = { 0 }; - если ее убрать, ошибка исчезает, но я не могу понять, а что не так с этим кодом то ??

main.cpp

 #include <iostream>      
    
    int main()
    {
    
    }

My_func.cpp

 #include <iostream>
    
    #include "My_class.h"
    
    
         My_class My_class_;
    
    
        int My_func()          
        {
            return 0;
        }

my_class.h

#pragma once


#include "My_struct_for_struct.h"


    class My_class
    {

    public:


        My_class()
        {
            my_struct_class = { 0 };
        }


    private:

        My_struct_for_struct my_struct_class;

    };

my_struct.h

#pragma once
#include <string>


    struct my_struct                                          
    {
        std::string my_string;                                                                            
    };



    struct My_struct_for_struct
    {
        my_struct my_struct_;    
    };

Ответы (1 шт):

Автор решения: KoVadim

Если убрать двойной уровень вложенности, и классы, то по факту, Вы хотите написать вот такой код

std::string s{0};

(да да, фигурные скобки "универсальной инициализации" обычно "очень жестоки" при несоответствии типов, но ноль это отдельная тема).

Этот код выглядит интересно, но он полулегален. Дело в том, что 0 в с++ по наследству от с конвертируется в NULL / nullptr.

У строки (а точнее у basic_string) есть конструктор, который принимает указатель на строку (что бы программист мог написать вот так вот

std::string s = "test";

)

Но компилятор не всегда может отличить указатель на строку от nullptr (по факту можно сделать специальную перегрузку, но это только для compile time).

И если посмотреть в доки (https://en.cppreference.com/w/cpp/string/basic_string/basic_string), то видно, что в 23 стандарте благодать снизошла и добавили такое

constexpr basic_string( std::nullptr_t ) = delete;

Но изначально разработчики стандарта приняли странное решение - на nullptr в конструкторе не проверять явно и никак не обрабатывать такой случай специально (да, странное решение).

там же в доках описано, что этот конструктор покрывает чуть больше случаев

  1. Constructs the string with the contents initialized with a copy of the null-terminated character string pointed to by s. The length of the string is determined by the first null character. The behavior is undefined if [s, s + Traits::length(s)) is not a valid range (for example, if s is a null pointer).

То есть, длина (и конец) строки определяется по нулевому символу. Если же полученный диапазон некорректный, то и поведение такое же. Случай с nullptr там описан отдельно и как по мне, то похоже это кто то просто не нашел лучше объяснения. (да, наверное тут имелось ввиду, что если нулевой символ будет найден вне приделов выделенной памяти под строку, то диапазон некорректный, но стандарт так сильно старается избегать явного упоминания простых вещей, что иногда заходит так далеко. А вот случай с nullptr, как мне кажется, тут сильно сильно притянут за уши. Видимо просто не смогли договорится, что именно делать в этом случае. Но это мои догадки)

Вот здесь https://groups.google.com/a/isocpp.org/g/std-proposals/c/PGdx39Iy8pg пишут, что это было сделано в целях производительности. Возможно.

Как показывает proposal p2166r1 проблема значительно глубже, чем изначально предполагали.

→ Ссылка