Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.144.187.103] |
|
Сообщ.
#1
,
|
|
|
Добрый вечер.
Прошу прощения за не вполне профессиональное объяснение проблемы, я не достаточно хорошо разбираюсь в С++. Есть сложный софт, исходники закрыты, есть только исходники пары модулей один из которых я сейчас переписываю / дорабатываю. Грубо говоря все на интерфейсах, сплошные CreateInterface() в библиотеках. Интерфейс (класс) который вызывается из основной программы или одного из ее модулей (и который имплементирован в моей DLL) имеет метод Refresh в который одним из параметров является IResponse - класс, содержащий 3 метода: Processed(int i), Failed(int i), Complete(). По мере работы моего метода Refresh я должен сообщать основной программе через IResponse->Processed() индексы прошедших объектов, через Failed - не прошедших, по окончании работы метода уведомить через Complete(). Как-то так было в исходном варианте, да и в моем все то же самое. При уведомлении через Processed() приложение запрашивает мой метод GetData где я возвращаю структуру данных заранее известного формата, это все отображается на экране в виде таблицы. Основное приложение слишком часто просто зависает до прибивания диспетчером задач, изредка вылетает без никаких MessageBox'ов, по тихому. Что касается вылетов - это в основном было из за багов в коде, переполнений и так далее, вроде бы все пофиксил. Зависания были и в исходном варианте, и сейчас (только я думал что они происходили из-за изначально неграмотной архитектуры и кучи создаваемых даром не нужных потоков, которую собственно и взялся переписывать - но, видимо, не только). В процессе вывода дебага нарисовывается такая картина: во первых, после каждого Processed() вызывается GetData для идентификатора от 0 до последнего, иногда не по порядку. Баг это или фича я не знаю, но это в основном приложении, исходников которого я не имею. В результате вместо запроса GetData N раз я получаю его порядка 1+2+3+4+...+N раз, но это не основное. При каких-то обстоятельствах вызов Processed завершается ошибкой. В смысле в поисках вылета я закмнул все что мог в __try и обнаружил что после Processed получается GetLastError = 183 (ERROR_ALREADY_EXISTS). То же самое при вызове Complete. Пример: проходит первый десяток Processed, после чего на 11-м элементе Processed вылетает с ошибкой 183, после чего все последующие тоже вылетают (а строки таблицы на экране уже не добавляются), в конце вызывается судя по логу Complete, завернутый тоже в __try, он завершается с той же ошибкой и эта строка в логе последняя - далее приложение не отвечает. Впрочем, может быть что GUI не отвечает и раньше но заметить это с точности до полсекунды невозможно. В mdmp файле этого процесса Visual Studio расшифровывает как код исключения 0xC0000005, "потоком была принята попытка прочитать или записать данные на виртуальный адрес, к которому он не имеет соответствующего доступа". Я точно знаю что данные отображаются только на экране, они не пишутся ни в какие файлы. Кто может вангануть почему может возникать ошибка 183? |
Сообщ.
#2
,
|
|
|
Для начала покажи хотя бы, что представляет из себя интерфейс IResponse. Я так понимаю реализовывал его ты, и, скорее всего, где-то накосячил.
|
Сообщ.
#3
,
|
|
|
Цитата Виталь @ Есть сложный софт, исходники закрыты, есть только исходники пары модулей один из которых я сейчас переписываю / дорабатываю. Грубо говоря все на интерфейсах, сплошные CreateInterface() в библиотеках. Эти модули (до переписывания) вызывали проблемы работы основной программы? |
Сообщ.
#4
,
|
|
|
Цитата Виталь @ Я точно знаю что данные отображаются только на экране, не пишутся ни в какие файлы. Кто может вангануть почему может возникать ошибка 183? Во-первых,в файл могут записываться не данные, а, например, тот же лог. Во-вторых, ошибка ERROR_ALREADY_EXISTS относится не только к файлам, но и ко многим (если не ко всем) именованным объектам (мьютексам, семафорам, разделяемой памяти и т.д.). Но в большинстве случаев это не ошибка, а просто индикатор того, что такой объект уже существует, т.е. некая Create-функция отрабатывает нормально, но возвращает хэндл не уникального (вновь созданного) объекта, а уже существующего. Поэтому не исключено, что истинная причина ошибки в чем-то другом, а GetLastError = 183 - просто старое значение от успешной Create-операции, не относящееся к делу. |
Сообщ.
#5
,
|
|
|
DLL представляет собой COM-сервер? Апартмент какой? Если не совпадает с требуемым, то по-любому задействуется маршалинг, и код ошибки скорее относится к объектам, создаваемым им самим для своих нужд.
Вообще, код ошибки в подобных случаях практически бесполезен. Он может относится к операциям, не имеющим никакого отношения к проблеме. Это не то же самое, когда ты вызвал API-функцию, она вернула неуспех, и ты поинтересовался GetLastError(), это вообще неизвестно какая функция неизвестно когда вызванная. Тут нужно применять другие методы поиска причин. Например, procexp посмотреть нитки и стеки, processexplorer собрать подробный журнал API-вызов и операций с объектами. Итп. Добавлено Цитата Виталь @ Просто похоже на то, что аппликуха перерисовывает табличку неэффективно, у себя данные не хранит, и потому после отображения каждой новой строки запрашивает все уже отрисованные ранее строки. Если что-то пропускается, значит WM_PAINT припозднилось, и аппликуха успела уйти чуть дальше по алгоритму. В процессе вывода дебага нарисовывается такая картина: во первых, после каждого Processed() вызывается GetData для идентификатора от 0 до последнего, иногда не по порядку. Баг это или фича я не знаю, но это в основном приложении, исходников которого я не имею. В результате вместо запроса GetData N раз я получаю его порядка 1+2+3+4+...+N раз |
Сообщ.
#6
,
|
|
|
Цитата Виталь @ Похоже на многопоточный доступ, GetData() вызывается более чем из одного потока, из-за этого нарушается порядок, это не баг и не фича... Это типичный механизм.В процессе вывода дебага нарисовывается такая картина: во первых, после каждого Processed() вызывается GetData для идентификатора от 0 до последнего, иногда не по порядку. Баг это или фича я не знаю, но это в основном приложении, исходников которого я не имею. В результате вместо запроса GetData N раз я получаю его порядка 1+2+3+4+...+N раз, но это не основное. Если GetData() не защищена от многопоточного доступа (хотя бы критические секции), то собственно и получается Цитата Виталь @ как результат одновременного доступа из двух потоков к данным.код исключения 0xC0000005, "потоком была принята попытка прочитать или записать данные на виртуальный адрес, к которому он не имеет соответствующего доступа". Если я не ошибаюсь, в студии можно даже увидеть к каким данным. |
Сообщ.
#7
,
|
|
|
Доброй ночи, спасибо всем кто откликнулся.
IResponse - реализовывал не я, исходников нет, черный ящик. 3 метода найдены в имеющихся исходниках. Да, этот модуль (до переписывания) вызывал вылеты, но я думал что это из-за создания сотни потоков там где это даром не надо. В лог данные действительно пишутся, но моим модулем (вывод в лог чуть ли не в каждой процедуре) и в другой лог еще одним модулем т.к. я включил в нем максимальный дебаг. Тот модуль, который содержит IResponse ничего в логи не пишет. GetData(i) выдает i-й элемент массива, на чтение, в него параллельно ничего не пишется (по крайней мере как я это понимаю). ОК, пару критических секций там не помешает, посмотрю на что это повлияет кроме производительности. |
Сообщ.
#8
,
|
|
|
Цитата Виталь @ И мне так же интересен результат. посмотрю на что это повлияет кроме производительности |