Как поймать ошибку?

Автор Тема: Как поймать ошибку?  (Прочитано 8466 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн LucaАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 0
Как поймать ошибку?
« : 03-02-2020, 12:29:20 »
Здравствуйте.
"Падает" приложение, притом Violation Access, те я даже StackTrace посмотреть не могу...
Как в такой ситуации найти ошибку...
Пробовал отлаживать (точки останова), вроде норм всё, до конца доходит приложение и на выходе падает.
Не соображу в чём дело.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Как поймать ошибку?
« Ответ #1 : 03-02-2020, 12:37:55 »
Общие рекомендации:
Смотрите окно "Output" ("Вывод") в Visual Studio при отладке. Есть шанс, что там будет полезная информация.
В настройках отладки добавить тип исключения "AccessViolationException" в список исключений, при которых останавливается отладка. Или ставить точку останова в начале команды и выполнять пошагово до тех пор, пока не упадёт. Это, как минимум, поможет понять в каком месте возникает исключение.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #2 : 03-02-2020, 12:58:44 »
Luca,
На этом форуме не гадают на кофейной гуще - нужен исходный код.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 470
  • Карма: 63
Re: Как поймать ошибку?
« Ответ #3 : 03-02-2020, 13:12:51 »
обычно это обращение к null-объекту

Отмечено как Решение Luca 03-02-2020, 13:31:23

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #4 : 03-02-2020, 13:15:25 »
обычно это обращение к null-объекту
Или к объекту, который открыт в транзакции, за пределами этой транзакции... Тут вариантов множество...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LucaАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 0
Re: Как поймать ошибку?
« Ответ #5 : 03-02-2020, 13:17:49 »
Автокад падает при команде  AUTO_ELECTRO_NUMBER_BLOCKS_
Решение разделено на части:
Общие вещи собраны в пространстве Common

Оффлайн LucaАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 0
Re: Как поймать ошибку?
« Ответ #6 : 03-02-2020, 13:18:57 »
обычно это обращение к null-объекту
из документации следует, что это грубая ошибка, сродни NullException, но только обращение за границы, а не к Null

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 470
  • Карма: 63
Re: Как поймать ошибку?
« Ответ #7 : 03-02-2020, 13:22:52 »
нельзя так делать
Код - C# [Выбрать]
  1.             public static List<BlockReference> getListOfBlocks(SelectionSet selectionSet, string layerName)
  2.             {
  3.                 List<BlockReference> listOfBlocks = new List<BlockReference>();
  4.                 Transaction transaction = startTransaction();
  5.                 using (transaction)
  6.                 {
  7.                     foreach (SelectedObject selectionSetObject in selectionSet)
  8.                     {
  9.                         if (selectionSetObject != null)
  10.                         {
  11.                             Entity entity = transaction.GetObject(selectionSetObject.ObjectId, OpenMode.ForRead) as Entity;
  12.                             if (entity is BlockReference block)
  13.                             {
  14.                                 if (block.Layer == layerName)
  15.                                 {
  16.                                     listOfBlocks.Add(block);
  17.                                 }
  18.                             }
  19.                         }
  20.                     }
  21.                     transaction.Commit();
  22.                 }
  23.                 if (listOfBlocks.Count != 0)
  24.                 {
  25.                     return listOfBlocks;
  26.                 }
  27.                 else
  28.                 {
  29.                     Application.ShowAlertDialog("[listOfBlocks:] НЕТ БЛОКОВ. КОЛИЧЕСТВО БЛОКОВ = " + listOfBlocks.Count);
  30.                     return null;
  31.                 }
  32.             }

Посмотри как у меня реализовано - функции CrTbl и GetSelect https://github.com/triroakenshield/tblPrs/blob/master/TableParser/MyTable.vb

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #8 : 03-02-2020, 13:28:31 »
нельзя так делать
Именно то, о чем я и писал выше.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LucaАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 0
Re: Как поймать ошибку?
« Ответ #9 : 03-02-2020, 13:30:20 »
обычно это обращение к null-объекту
Или к объекту, который открыт в транзакции, за пределами этой транзакции... Тут вариантов множество...
Так и есть!
У меня было ощущения, судя по отладке. что с транзакцией что-то не то, но понять что именно я не мог.
Как только Вы сказали, то я сразу нашел transaction.Commit, который не в тех операторных скобках.
Ох, спасибо...

Оффлайн LucaАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 0
Re: Как поймать ошибку?
« Ответ #10 : 03-02-2020, 13:30:45 »
нельзя так делать
Именно то, о чем я и писал выше.
да, я уже понял ... нашел. Спасибо.

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 470
  • Карма: 63
Re: Как поймать ошибку?
« Ответ #11 : 03-02-2020, 13:32:10 »
Цитировать
то я сразу нашел transaction.Commit, который не в тех операторных скобках.
он то как раз там где надо

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #12 : 03-02-2020, 13:35:03 »
Как только Вы сказали, то я сразу нашел transaction.Commit, который не в тех операторных скобках.
У тебя в Common.cs  полный бред, который даже сложно комментировать.
Например,
Код - C# [Выбрать]
  1.             public static BlockTableRecord getBlockByNameFromDocument(string blockName)
  2.             {
  3.                 Transaction transaction = startTransaction();
  4.  
  5.                 BlockTable blockTable = (BlockTable)transaction.GetObject(database.BlockTableId, OpenMode.ForRead);
  6.                 foreach (ObjectId btrID in blockTable)
  7.                 {
  8.                     BlockTableRecord btr = (BlockTableRecord)transaction.GetObject(btrID, OpenMode.ForWrite);
  9.                     if (btr.Name.ToUpper() == blockName.ToUpper())
  10.                     {
  11.                         return btr;
  12.                     }
  13.                 }
  14.                 return null;
  15.             }
1. Запускается транзакция, но нет ни transaction.Dispose() ни transaction.Commit()
2. Из метода возвращается BlockTableRecord, открытый в транзакции.

Т.е. нужно переделывать всё логику методов.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LucaАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 0
Re: Как поймать ошибку?
« Ответ #13 : 03-02-2020, 13:44:30 »
Как только Вы сказали, то я сразу нашел transaction.Commit, который не в тех операторных скобках.
У тебя в Common.cs  полный бред, который даже сложно комментировать.
Например,
Код - C# [Выбрать]
  1.             public static BlockTableRecord getBlockByNameFromDocument(string blockName)
  2.             {
  3.                 Transaction transaction = startTransaction();
  4.  
  5.                 BlockTable blockTable = (BlockTable)transaction.GetObject(database.BlockTableId, OpenMode.ForRead);
  6.                 foreach (ObjectId btrID in blockTable)
  7.                 {
  8.                     BlockTableRecord btr = (BlockTableRecord)transaction.GetObject(btrID, OpenMode.ForWrite);
  9.                     if (btr.Name.ToUpper() == blockName.ToUpper())
  10.                     {
  11.                         return btr;
  12.                     }
  13.                 }
  14.                 return null;
  15.             }
1. Запускается транзакция, но нет ни transaction.Dispose() ни transaction.Commit()
2. Из метода возвращается BlockTableRecord, открытый в транзакции.

Т.е. нужно переделывать всё логику методов.
метод  getBlockByNameFromDocument пока просто лежит, на будущее, я его не использую.
прям всё и переделывать?
в Common общие для методы и констаны для всех операций, типа получение транзакции, получение предварительного выбора и тд
теперь в следующей команде  AUTO_ELECTRO_CREATE_CABLE_LOG_  тоже Violation Access

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #14 : 03-02-2020, 13:48:58 »
теперь в следующей команде  AUTO_ELECTRO_CREATE_CABLE_LOG_  тоже Violation Access
Никогда не храни открытые объекты/примитивы - храни их ObjectId. И открывай по мере надобности.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LucaАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 0
Re: Как поймать ошибку?
« Ответ #15 : 03-02-2020, 13:50:16 »
У тебя в Common.cs  полный бред, который даже сложно комментировать.
обсуждалось здесь
https://adn-cis.org/forum/index.php?topic=9705.0
нужно переделывать всё логику методов.
зачем всю логику переделывать всех методов?

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 470
  • Карма: 63
Re: Как поймать ошибку?
« Ответ #16 : 03-02-2020, 13:53:13 »
Цитировать
обсуждалось здесь
ага
Цитировать
для получения ObjectId того BlockTableRecord

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #17 : 03-02-2020, 13:55:12 »
зачем всю логику переделывать всех методов?
Я не знаю как мне еще нужно объяснять про открытые примитивы/объекты вне транзакций, а у тебя это на каждом шагу. Не должно быть глобальных List<Polyline>, List<BlockReference> и т.д.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LucaАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 0
Re: Как поймать ошибку?
« Ответ #18 : 03-02-2020, 13:56:27 »
Никогда не храни открытые объекты/примитивы - храни их ObjectId. И открывай по мере надобности.
не совсем понял о чем речь

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #19 : 03-02-2020, 13:58:29 »
не совсем понял о чем речь
Ты хранишь между запусками команд вот такое: List<BlockReference>, List<Polyline> - этого делать категорически нельзя. Вместо этого храни List<ObjectId> для вставок блоков и полилиний и если нужны их данные - открывай их по мере надобности.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 470
  • Карма: 63
Re: Как поймать ошибку?
« Ответ #20 : 03-02-2020, 14:00:28 »
Цитировать
этого делать категорически нельзя
а я делаю  ::)
Код - C# [Выбрать]
  1.         public void DrawLayer(Data.DataLayer wl)
  2.         {
  3.             //List<Entity> wEntlist = new List<Entity>();
  4.             Autodesk.Gis.Map.ObjectData.Table wTbl = null;
  5.             if (wl.HasAttributes()) wTbl = CreateODTable(wl._Rule);
  6.             ObjectId wid;
  7.             Entity wEnt;
  8.             Geometry.TGeometry g;
  9.             foreach (Data.MyRecord wr in wl.Table)
  10.             {
  11.                 g = wr.GetGeometry();
  12.                 if (g != null)
  13.                 {
  14.                     wEnt = MakeGeometry(g);
  15.                     wid = DrawEntity(wEnt);
  16.                     if (wl.HasAttributes()) AddAttr(wid, wr, wTbl);
  17.                 }
  18.                 //wEntlist.Add(wEnt);
  19.             }
  20.             //DrawEntity(wEntlist);
  21.         }
https://github.com/triroakenshield/RosReestrImpLib/blob/master/RosReestrImp/MyCommands.cs

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #21 : 03-02-2020, 14:04:33 »
а я делаю 
wEnt у тебя содержится в Database (т.е. ObjectId у него не null) или только в памяти?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 470
  • Карма: 63
Re: Как поймать ошибку?
« Ответ #22 : 03-02-2020, 14:06:34 »
Только в памяти  ;D, а DrawEntity добавляет его в Database и возвращает ObjectId - с которым дальше и работаю!

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #23 : 03-02-2020, 14:08:40 »
Только в памяти  ;D, а DrawEntity добавляет его в Database и возвращает ObjectId - с которым дальше и работаю!
Ну так совсем другое дело...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LucaАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 0
Re: Как поймать ошибку?
« Ответ #24 : 03-02-2020, 14:11:56 »
Вместо этого храни List<ObjectId> для вставок блоков и полилиний и если нужны их данные - открывай их по мере надобности.
c этого момента подробнее, пожалуйста... если можно, конечно
что значит открываешь? просто работа очень много и читать исходники, пока, времени просто нет...
не совсем понимаю пока в каких абстрактных типах данных (АТД) всё это хранится, поэтому так и поступаю.
по-идее, как я это понимаю, BlockReference - ссылка ( разыменованный указатель), те указатель, но при обращении к нему получаем АТД. ObjectID, исходя из названия, это какой-то ключ для получения Object из Dictonary, например или какой-то древовидной структуры.
Можно пример, как имея BlockReference получить ObjectID и обратно. ObjectId это ключ для получения BlockReference из какой-то структуры, АТД - что это за структура?
Честно сказать, у меня мозги "заплелись" немного ))

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 470
  • Карма: 63
Re: Как поймать ошибку?
« Ответ #25 : 03-02-2020, 14:14:50 »
Код - vb.net [Выбрать]
  1.     Public Shared Function CrTbl(acDoc As MyAcAs.Document) As MyTable
  2.         'Создаём таблицу
  3.         Dim ed As Editor = acDoc.Editor
  4.         Dim objIdArray() As ObjectId = MyTable.GetSelect(ed) 'Получаем от пользователя набор данных для парсинга
  5.         If objIdArray IsNot Nothing Then
  6.             Dim dbObj As DBObject
  7.             Dim wList As New List(Of Line)
  8.             Dim wTList As New List(Of DBText)
  9.             Dim wMTList As New List(Of MText)
  10.             Using tr As Transaction = acDoc.Database.TransactionManager.StartTransaction
  11.                 Try
  12.                     For Each objId As ObjectId In objIdArray
  13.                         dbObj = tr.GetObject(objId, OpenMode.ForRead)
  14.                         'Сортируем полученные объекты
  15.                         Select Case True
  16.                             Case TypeOf dbObj Is Line
  17.                                 wList.Add(dbObj)
  18.                             Case TypeOf dbObj Is Polyline
  19.                                 wList.AddRange(MyTable.PolyToLine(dbObj))
  20.                             Case TypeOf dbObj Is DBText
  21.                                 wTList.Add(dbObj)
  22.                             Case TypeOf dbObj Is MText
  23.                                 wMTList.Add(dbObj)
  24.                         End Select
  25.                     Next
  26.                     tr.Commit()
  27.                 Catch ex As Exception
  28.                     ed.WriteMessage(ex.ToString())
  29.                     tr.Abort()
  30.                 End Try
  31.             End Using
  32.             '
  33.             Dim wMTbl As MyTable = MyTable.CrTbl(wList)
  34.             'Заполняем текстом
  35.             For Each wt In wTList
  36.                 wMTbl.SetValue(wt)
  37.             Next
  38.             For Each wmt In wMTList
  39.                 wMTbl.SetValue(wmt)
  40.             Next
  41.             Return wMTbl
  42.         Else
  43.             Return Nothing
  44.         End If
  45.     End Function
блин, неправильный пример... но ведь работает
« Последнее редактирование: 03-02-2020, 14:28:15 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #26 : 03-02-2020, 14:24:20 »
Честно сказать, у меня мозги "заплелись" немного ))
Извини, но это единственно что я вынес из твоего сообщения. Не лезь в абстракции. Делай то, что я тебе подсказываю, иначе ты потратишь уйму времени на написание кода, который будет работать через раз и ты будешь создавать постоянно темы, аналогичные этой.
Открытие объекта это или tr.GetObject(id,...) или id.Open(...) - в результате из ObjectId получаем одного из наследников DBObject (например, Entity или BlockTableRecord). Закрытие объекта, открытого через id.Open(...) - это метод Close, а для открытого в транзакции - это или tr.Commit() или tr.Dispose()
Если объект открыт (например, BlockReference) в одной из твоих команд и не закрыт в ней (хранится в static переменной), то это значит, что ни сам AutoCAD, ни другие приложения к нему обратиться уже не смогут.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #27 : 03-02-2020, 14:26:51 »
блин, неправильный пример... но ведь работает
Для объектов, открытых ForRead такое иногда работает. Но зачем наступать на грабли???
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Онлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
Re: Как поймать ошибку?
« Ответ #28 : 09-06-2020, 15:50:05 »
Прошу прощения за некропостинг, но может кто-то объяснит почему автор везде пихает static?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как поймать ошибку?
« Ответ #29 : 09-06-2020, 15:56:36 »
Прошу прощения за некропостинг, но может кто-то объяснит почему автор везде пихает static?
1. Это не некропостинг - этой теме всего-то четыре месяца.
2. static бывает достаточно удобен для утилитных функций, которые можно вызвать без создания самого объекта класса.
Но почему автор решил использовать static наверное у автора и нужно спрашивать. Впрочем подозреваю, что с его стороны это просто "копипастинг" готового метода, найденного на просторах интернет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение