#c#
Вопрос:
мой код работает нормально, но через 5-10 минут я получаю следующую ошибку;
Помощник по управляемой отладке «FatalExecutionEngineError»: «Среда выполнения обнаружила фатальную ошибку. Адрес ошибки был 0x641ad419, в потоке 0x5d0c. Код ошибки 0xc0000005. Эта ошибка может быть ошибкой в CLR или в небезопасных или неподтверждаемых частях пользовательского кода. Распространенные источники этой ошибки включают ошибки маршалинга пользователей для COM-взаимодействия или PInvoke, которые могут привести к повреждению стека.
Вызывается из разных потоков;
InvokeUtil.getInstance.Calculate(localVal);
Мой Код;
public class InvokeUntil
{
private IntPtr m_object = IntPtr.Zero;
private static InvokeUntil Self;
private InvokeUntil()
{
this.m_object = InvokeUntil.DllCreateInstance();
}
[DllImport("xDll")]
private static extern IntPtr DllCreateInstance();
[DllImport("xDll")]
private static extern void DllDisposeInstance(IntPtr CSObject);
[DllImport("xDll")]
private static extern void DllCalculate(IntPtr pCSObject, byte[] pCurrentData, uint[] pResult);
public static InvokeUntil getInstance
{
get
{
if (InvokeUntil.Self == null)
InvokeUntil.Self = new InvokeUntil();
return InvokeUntil.Self;
}
}
public void Calculate(uint[] EffVal)
{
InvokeUntil.DllCalculate(m_object, Data.MyData, EffVal);
}
}
Комментарии:
1. На первый взгляд, я бы предположил, что это может быть проблемой параллелизма. Я вижу, что DLL поддерживает
DllCreateInstance
метод, который, по-видимому, предполагает, что он поддерживает какое-то состояние. Является ли вызовDllCalculate
потокобезопасным в DLL? Я бы предположил, что нет2. @Martin Очевидно, что я не могу видеть содержимое библиотеки dll. Но ты имеешь в виду, что я должен позвонить? ; InvokeUtil.DllDisposeInstance (m_object);
3. Я имею в виду, что экземпляр
m_object
не является потокобезопасным, поэтому вызов его более одного раза одновременно вызовет проблему параллелизма.4. Поскольку это прерывистый сбой, обычно происходит одна из двух вещей: 1) Это проблема выравнивания. Вашему приложению предоставляется диапазон памяти, который может быть измерен в байтах. Если параметры компилятора не настроены в соответствии с dll, вы можете превысить объем памяти на несколько байтов, если режим выравнивания (1,2,4,8 байта) установлен правильно 2) Проблема в коде dll.
5. DllCalculate() нельзя безопасно записать, он понятия не имеет, насколько большими могут быть массивы. Запись за пределами массива приводит к повреждению кучи GC, что в конечном итоге приводит к срабатыванию FEEE, когда сборщик мусора замечает повреждение. Исправьте это, добавив параметр, который передает EffVal. Длина, так что теперь возможна правильная проверка ошибок.