Какой предел памяти в WinXP при получении обратного вызова из С++ DLL в С#?
У меня есть приложение С#, которое использует неуправляемую DLL на С++. Я обнаружил сбой, который происходит только в WinXP (не Win7), когда память, которую я передаю из библиотеки С++, слишком велик.
Основной поток - это то, что С# запускает операцию в С++ DLL, вызывая функцию запуска, в которой он обеспечивает обратный вызов. Затем DLL С++ выполняет операцию и записывает информацию о регистрации в текстовый буфер. Когда операция завершена, С++ DLL вызывает обратный вызов и передает текстовый буфер в качестве параметра:
С++:
typedef void (CALLBACK *onfilecallbackfunc_t)(LPCWSTR);
DLL_API void NWAperture_SetOnFileCallback(onfilecallbackfunc_t p_pCallback);
l_pFileCallback(_wstringCapture.c_str());
С#:
public delegate void FileCallback([MarshalAs(UnmanagedType.LPWStr)] string buffer);
public static extern void SetOnFileCallback(FileCallback fileCallback);
private void OnFile(string buffer);
Это отлично работает в Win7, но в WinXP, если буфер становится слишком большим, он сбой. Я не уверен в точных размерах, которые приводят к этому, но я наложил на него ограничение в 8 МБ, и авария исчезла.
Кто-нибудь знает о пределе объема памяти, который может быть передан между С++ и С#, как это в WinXP? Или я полностью неправильно понял эту проблему и там более логичное объяснение?
Обновление: я должен был быть более конкретным - это происходит на том же ПК с двойной загрузкой WinXP и Win7, как с 32-разрядной ОС.
Ответы
Ответ 1
Итак, в итоге оказалось, что я идиот. Чтобы сделать журнал большим, но ускорить тестирование, я нажал кнопку отмены, которая вызвала функцию в С++ DLL, которая прекратила выполнение, и вызвала функцию обратного вызова с ошибкой "abort" и тем, что уже был записан. Но когда я это сделал, выполнение не прекратилось немедленно, поэтому, когда был выполнен обратный вызов с журналом, код С++ может попытаться добавить в журнал. Это вызвало нестабильность, которую я наблюдал.
Я исправил его, используя критический раздел вокруг журнала.
Ответ 2
У вас может закончиться непрерывный путь памяти до того, как вы на самом деле закончите RAM. Это одна большая сторона использования буферов Array. LinkedLists (или массивы с использованием chunking) помогают смягчить эту проблему, потому что пространство, в котором вы нуждаетесь, не должно быть смежным.
Поэтому, если ваше приложение не использует 2 ГБ ОЗУ, чем ваша проблема, скорее всего, фрагментация памяти, чем что-либо еще.
Windows 7, вероятно, управляет ОЗУ иначе, чем Windows XP, вероятно, почему вы не видите проблему там. Но проталкивайте больше данных, и я уверен, что вы столкнетесь с тем же вопросом.
Вы можете настроить perfmon для отслеживания/использования памяти журнала вашей системы и диспетчера задач для отслеживания вашего приложения.
Ответ 3
Я не знаю никаких жестких ограничений, установленных Windows или NETFX, но я очень подозрительно, что объем данных, возвращаемых из вашего С++-приложения, может быть совершенно произвольным, и это может привести к изменчивому поведению.
Я настоятельно рекомендую записать ваши данные журнала в файл в вашем родном компоненте, а затем прочитать файл из вашего управляемого кода. Таким образом, неважно, сколько данных записано, ваш управляемый код может анализировать его, не беспокоясь о том, чтобы выдуть кучу.