Распределение динамической памяти в собственной dll

У меня есть собственный (неуправляемый) .dll, написанный на C++, который должен вызываться из управляемого процесса (программа на C#). При отладке dll проблема, которую я показал, заключается в том, что когда я создаю объект в dll с ключевым словом new, я получаю исключение нарушения доступа к системе. Это проявляется только при вызове библиотеки DLL из управляемого процесса, а не когда я вызываю ее из другой собственной программы.

Код похож на этот:

// Native.dll file
MyClass myInstance; // global variable (and does need to be so)
__declspec(dllexport) uint8_t _stdcall NativeFunction(){
    myInstance = new MyClass(); // <-- this causes Access Violation Exception
}

и код C#:

using System.Runtime.Interopservices;
// Loading the dll
[DllImport("Native.dll",CallingConvention = CallingConvention.StdCall)]
private extern static byte NativeFunction();

class TestClass{
   byte returnVal = NativeFunction(); //<-- exception in managed context
}

Я знаю, что это как-то связано с тем, что собственный процесс пытается выделить память за пределами разрешенного пространства памяти. Это происходит только тогда, когда память выделяется с помощью new (по крайней мере, в этом проекте), который, к сожалению, мне нужно использовать. Мой вопрос: кто-нибудь знает, почему это вызывает исключение и как его избежать?

3
0
459
1

Ответы 1

new MyClass, скорее всего, вызовет ::operator new, глобального оператора, если вы не предоставили MyClass::operator new. И если вы сами не предоставили ::operator new, вы должны получить ::operator new из своего компилятора (вероятно, Visual Studio).

Эта реализация ::operator new, вероятно, будет направлена ​​на HeapAlloc. И угадай что? Это та же самая функция Win32, которую также будет вызывать .Net. Здесь не так уж много магии; вот как Windows назначает страницы памяти вашему виртуальному адресному пространству. И когда вы используете эти страницы, Windows назначит оперативную память.

Дело в том, что для этого не нужно делать ничего особенного. Фактически, делать что-то особенное - это то же самое, что и перерывoperator new. И раз уж вы его сломали, вам придется в этом разобраться. Здесь не так уж много магического кода. Используйте отладочную сборку, чтобы получить четкий дамп стека (без встраивания). Можете ли вы вернуться к HeapAlloc?

Также проверьте содержание исключения нарушения доступа. Код ошибки будет C0000005. Но что это за исключение? Читать или писать? По какому типу адреса? Код или данные?

Итак, сообщение - Exception thrown at 0x001E15D9 in TheManagedCode.exe: 0xC0000005: Access violation reading location 0x00000004.. Я не уверен, что полностью следую за вами здесь; Если я не предоставил свой собственный ::operator new, как тогда его сломать?

skitiddu 11.04.2018 14:28

@skitiddu: Ну, поскольку вы не предоставили эту информацию заранее, я рассмотрел несколько случаев. Итак, проблема здесь в читать. Очевидно, это разыменование нулевого указателя, но почему? Следующий бит информации - это инструкция, которая его вызвала, на 0x001...... Вероятно, это в EXE. Почему это там? Статический ЭЛТ? operator new обычно находится в DLL (поскольку вы хотите, чтобы он использовался всеми модулями).

MSalters 11.04.2018 15:20

Другие вопросы по теме