Исключение времени выполнения в операторе удаления std::string при преобразовании System::String в std::string

Я использую решение C++ cli с кодом C# и C++.

Когда я пытаюсь преобразовать System::String в std::string, я получаю следующее исключение времени выполнения при каждом запуске:

ucrtbased.dll!00007ffd9902b9b0()    Unknown
ucrtbased.dll!00007ffd9902eac5()    Unknown
MyApp.dll!operator delete(void * block) Line 21 C++
[Managed to Native Transition]  
MyApp.dll!std::_Deallocate(void* _Ptr, unsigned __int64 _Count, unsigned __int64 _Sz) Line 133  C++
MyApp.dll!std::allocator<char>::deallocate(char* _Ptr, unsigned __int64 _Count) Line 721    C++
MyApp.dll!std::_Wrap_alloc<std::allocator<char> >::deallocate(char* _Ptr, unsigned __int64 _Count) Line 988 C++
MyApp.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy(bool _Built, unsigned __int64 _Newsize) Line 2260 C++
MyApp.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::=(std::basic_string<char,std::char_traits<char>,std::allocator<char> >& _Right) Line 934    C++
MyApp.dll!MyApp::DoStuff(System::String^ input) Line 59 C++

Или когда я запускаю без отладчика:

ошибка

Мой код, я попробовал два варианта, оба привели к одному и тому же сбою:

Опция 1

void MyApp::DoStuff(System::String^ input) {
    msclr::interop::marshal_context context;
    std::string converted = context.marshal_as<const char*>(LicenseOEM);
}

Вариант 2

std::string SystemToStd(System::String^ sys) {
    int len = sys->Length;
    char* buff = (char*)malloc((len + 1) * sizeof(char));
    for (int i = 0; i < sys->Length; i++) {
        buff[i] = sys[i];
    }
    buff[len] = '\0';
    std::string str = std::string(buff, len);
    free(buff);
    return str;
}

void MyApp::DoStuff(System::String^ input) {
    std::string converted = SystemToStd(LicenseOEM);
}

person Mugen    schedule 18.03.2018    source источник
comment
Не должен быть помечен как C++. C++/CLI — это независимый язык в соответствии с ECMA-372. C++/CLI (по сравнению с C++) так же, к сожалению, называется, как JavaScript (по сравнению с Java).   -  person Eljay    schedule 18.03.2018
comment
Что ж, при всем уважении к разнице, мой стек имеет код C++, поэтому он не может быть таким далеким от этого тега.   -  person Mugen    schedule 18.03.2018


Ответы (1)


может быть, это тема C++ сама по себе.

Вы обеспечили привязку правильных/подходящих/одинаковых библиотек времени выполнения для вашей конфигурации.

DLL-файлы отладки от Microsoft (остальные, которых я не знаю) пытаются выяснить, не портит ли кто-нибудь память. Они делают это, предоставляя другую реализацию new/delete. В основном они увеличивают выделенную память, чтобы иметь неиспользуемую память до и после выделенной памяти. Затем они заполняют его шаблоном и информацией и дают вам указатель на ваш объект. При удалении/освобождении объекта они получают правильное значение для вашей области памяти и контролируют информацию, а также если кто-то перезаписал шаблоны до и после вашего объекта.

Итак, вы пытаетесь связать dll, которая была скомпилирована с выпуском в качестве конфигурации. Но теперь вы пытаетесь что-то выяснить, используете отладку и забываете, что ваши библиотеки времени выполнения не совпадают, тогда ваш код создает их с отладочной информацией, но вы предоставляете этот объект нативной/cpp-функции, который был скомпилирован с выпуском и попыткой освободить объект, который не работает. Или наоборот выпуск std:string освобождается с помощью удаления отладки.

На самом деле я погуглил ваше сообщение об ошибке и некоторые подсказки в том же направлении, так что вы можете перепроверить Ошибка утверждения отладки! Выражение: __acrt_first_block == заголовок

person JackGrinningCat    schedule 19.03.2018
comment
На самом деле проблема заключалась в том, что некоторые dll C++ использовались в Debug, а другие в Release. - person Mugen; 22.03.2018