Solidworks, отслеживание ошибки нарушения доступа к памяти на Isldworks.CloseDoc
У меня есть две разные функции внутри аддона, над которым я работал в C#. В последнее время (по-видимому) Solidworks терпит крах, когда он добирается до определенных частей этих двух функций (возможно, больше, но это единственные два, которые я нашел до сих пор.) В разделе debug обе функции дают мне "ошибку нарушения доступа к памяти". Эта ошибка возникает каждый раз в строке, где я закрываю активный документ, и происходит примерно в 95% случаев.
Это почти всегда с одной и той же стороны. Кажется, что он не зависит от времени выполнения или количества частей, которые были открыты и закрыты. Если я не закрою файлы, я, похоже, не получу ошибку. Но при запуске большой сборки это представляет свои собственные проблемы. Добавление в 1S ожидания перед закрытием, кажется, уменьшает частоту ошибки (как и в, Я иногда могу пройти через всю сборку без ошибки)
быстрое объяснение того, что функция, о которой я в первую очередь беспокоюсь, выполнение; он работает с верхнего уровня сборки вниз, распространяя пользовательские свойства из основной сборки и сборок в их дочерние элементы. Поэтому я постоянно открываю и закрываю различные файлы сборок и деталей.
приведенный ниже код был разделен почти до минимума, который реплицирует ошибку. Ошибка возникает в строке 59. Из того, что я видел в интернете до сих пор, кажется, что их трудно отследить. Любая помощь очень оцененный.
public void propagateProps(bool overwrite)
{
List<string> assemblies = new List<string>();
string topAssem;
string compName = "";
int i = 0;
int j = 0;
int errors = 0, warnings = 0;
int partType = 1;
swModel = iSwApp.ActiveDoc;
if (swModel == null)
{
MessageBox.Show("No assembly document open. Please open an assembly and try again.", "Avengers Assemble Error");
return;
}
if (swModel.GetType() != 2)
{
MessageBox.Show("No assembly document open. Please open an assembly and try again.", "Avengers Assemble Error.");
return;
}
topAssem = swModel.GetPathName();
assemblies.Add(swModel.GetPathName());
swAssy = iSwApp.ActiveDoc;
while (i < assemblies.Count)
{
List<string> beenDone = new List<string>();
iSwApp.OpenDoc(assemblies[i], 2);
swModel = iSwApp.ActivateDoc(assemblies[i]);
swAssy = iSwApp.ActiveDoc;
foreach (Component2 swComp in swAssy.GetComponents(true))
{
partType = 1;
compName = swComp.GetPathName();
if (compName.IndexOf(").SLD") > 0 || compName.IndexOf("REF") > 0)
{
continue;
}
if (Path.GetExtension(compName).ToUpper() == ".SLDASM")
{
partType = 2;
assemblies.Add(compName);
}
iSwApp.OpenDoc(compName, partType);
swModel = iSwApp.ActivateDoc(compName);
if (swModel == null)
{
continue;
}
#region things that might not be in
#endregion
boolstatus = swModel.Save3(5, errors, warnings);
System.Threading.Thread.Sleep(500);
iSwApp.CloseDoc(swModel.GetPathName());
swPart = null;
swModel = null;
}
++i;
System.Threading.Thread.Sleep(500);
}
return;
}
Update: после просмотра этого вопроса;что вызывает нарушение доступа к памяти? Я попытался возиться с некоторыми глобальными переменными, которые я использую в своих функциях, безрезультатно. Однако мне удалось обернуть мой основной код в другую логическую структуру для циклического прохождения частей, которые, похоже, избегают этой проблемы. Но я чувствую, что это в лучшем случае пластырь и хотел бы избежать этой проблемы в будущем.
1 ответов
вы пишете код на C# - если вы не работаете с PInvokes, небезопасными блоками или подобными, для вас должно быть невозможно вызвать исключения доступа к памяти. Единственный разумный ответ тогда заключается в том, что SolidWorks имеет ошибку, которая либо приводит к сбою с учетом разумных входных данных, либо приводит к сбою, потому что она не проверяет необоснованные входные данные.
реальным исправлением было бы связаться с SolidWorks, чтобы они воспроизвели ошибку и исправили ее; за исключением этого, мы могли бы проанализировать ваш код для поиска взаимодействий, которые являются общими триггерами ошибок и ошибок. Например, они могут неправильно проверять все свои входные данные - вы можете предоставить недопустимые значения, которые они молча принимают; это не сломается намного позже.
если вы случайно передавали null, и они не проверяли, это может привести к нарушениям доступа к памяти, если они позже попытаются взять указатель из этого null. Если вы использовали ресурсы после их закрытия, а они не были проверяя для такого условия, они могут использовать устаревший указатель под капотом, также вызывая нарушение доступа к памяти.
в других ситуациях асинхронные операции могут быть причиной ошибки - если вы запустите некоторую асинхронную операцию, а затем закройте ресурс, привязанный к этой операции, когда эта операция позже будет выполняться в фоновом режиме, это может вызвать ошибки.
возможно, что способ использования возвращенных вам дескрипторов вызывает нарушения доступа к памяти. Я заметил, что вы не используете возвращаемое значение из OpenDoc
, а вместо этого попытаться получить доступ к документам другими средствами. Что происходит, когда возвращаемое значение OpenDoc
получает собранный мусор? Возможно, SolidWorks неправильно подсчитывает ссылки, и поэтому, когда возвращаемое значение GC'D, дескриптор под капотом закрыт и обнулен; однако другие операции по-прежнему ожидают, что он будет действительным и, таким образом, вызовет нарушения доступа к памяти.
также возможно, что вы используете устаревший API-если это так, возможно, вы используете код в SolidWorks, который имеет более высокую вероятность ошибки, поскольку он больше не тестируется или не поддерживается. Я заметил, что вы вызываете OpenDoc
метод, который в их документации указан как устаревший. Вместо этого рекомендуется использовать такие методы, как OpenDoc6
.
за пределами исправления реальной проблемы с API либо сломан, или не проверяя против сломанных входов достаточно хорошо, ваш единственный вариант - исследуйте эти источники общих проблем API.