Стек среды C # переполняется при запуске DLL - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть часть программы на C #, загружающая функцию dll:

[DllImport("/Users/frk/Workspaces/MySharedLibrary.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, EntryPoint = "MyCFunction")]

public static extern int MyFunction( [In][MarshalAs(UnmanagedType.I4)]MyFormat format,  [In][MarshalAs(UnmanagedType.LPArray)] byte[] myString,  [In][MarshalAs(UnmanagedType.I4)] int myStringLength, [MarshalAs(UnmanagedType.LPArray)] byte[] output,  ref UIntPtr outputLength);

и вызывающая ее

int result = MyFunction(format, inPut, inputLength, outPut, ref outputLength);

на стороне C ++, у меня есть:

MyCPPFunction, которая отлично работает при вызове из исполняемого файла теста C.Эта функция MyCPPFunction содержит где-то глубоко в своих зависимостях глобальную переменную const, объявленную и инициализированную в анонимном пространстве имен:

namespace
{
        constexpr unsigned RandTileSize = 256;

        std::array<unsigned, RandTileSize * RandTileSize> GenerateSamples()
        {
            std::array<unsigned, RandTileSize * RandTileSize> samples;

            std::mt19937 rd(0);
            std::uniform_int_distribution<unsigned> distribution(0, 255);

            for (unsigned i = 0; i < RandTileSize * RandTileSize; ++i)
            {
                samples[i] = distribution(rd);
            }

            return samples;
        };

        const auto samples = GenerateSamples();<-- Option#1 this causes a stack overflow when loading the dll in C# environment

        unsigned Sample(unsigned index)
        {
               static const auto samples = GenerateSamples();<-- Option#2 this works and dll loads correctly
               return samples[index];
        }
}

Я запутался здесь, поскольку afaik, опция 1 должна выделять память в части кода dll,какая среда C # должна работать правильно?

Как у нас может быть опция # 1, чтобы не вызывать проблемы с выделением памяти при загрузке DLL?

1 Ответ

0 голосов
/ 20 сентября 2018

Время жизни статической переменной в функции внутри DLL - с момента первого обращения к инструкции до момента выгрузки DLL.

Время жизни переменной класса или области файла - извремя загрузки DLL до момента выгрузки DLL.

Следствием этого является то, что в случае сбоя ваш код инициализации выполняется , в то время как DLL находится в процессе загрузки .

Обычно не рекомендуется запускать нетривиальный код в конструкторах классов, поскольку существуют ограничения на то, что можно безопасно сделать внутри блокировки загрузчика.

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

Без точной диагностики того, что пошло не так в вашем случае, ответ прост: используйте опцию 2 или опцию 3.

Опция 3:

void MyDLLInitialize(){
    // Initialize the dll here
}

void MyDLLUninitialize(){
   // Uninitialize the dll here
}

Затем вызовите эти функции из C #, прежде чем использоватьлюбую другую функцию DLL, и после того, как вы с ней закончили, соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...