Форум: "Начинающим";
Текущий архив: 2011.06.26;
Скачать: [xml.tar.bz2];
ВнизAV в ntdll.dll...? Найти похожие ветки
← →
istok (2011-03-16 22:46) [0]есть такой код для записи в файл:
CS: SyncObjs.TCriticalSection;
....
procedure WriteLog(Str: string; AFileName: string);
var
f: TextFile;
begin
CS.Enter;
try
AssignFile(f, AFileName);
try
if FileExists(AFileName) then
Append(f)
else
Rewrite(f);
Writeln(f, Format("[%s](%d): %s", [DateTimeToStr(Now), GetCurrentThreadId, str]));
finally
CloseFile(f);
end;
finally
CS.Leave;
end;
end;
при интенсивном использовании этого кода разными потоками иногда получаю вот это (eurekalog):
Access violation at address 00000000. Read of address 00000000.
---------------------------------------------------------------------------------------------------------------
|Address |Module |Unit |Class |Procedure/Method |Line |
---------------------------------------------------------------------------------------------------------------
|Running Thread: ID=10680; Priority=??; Class= |
|-------------------------------------------------------------------------------------------------------------|
|775E7760|ntdll.dll | | |RtlLeaveCriticalSection | |
|775E6A22|ntdll.dll | | |NtWaitForSingleObject | |
|775E7012|ntdll.dll | | |KiUserExceptionDispatcher | |
|0053F1CA|wecmsg.exe |WebFilterUnit.pas |TWebFilter |InStrings |2016[3] |
|0053F17C|wecmsg.exe |WebFilterUnit.pas |TWebFilter |InStrings |2013[0] |
|0053F655|wecmsg.exe |WebFilterUnit.pas |TWebFilter |CheckForBlockedUrl |2131[53]|
Метод InStrings через цепочку событий (синхронизируются) в итоге вызывает WriteLog:function TWebFilter.InStrings(AStr: string; AStrings: TStrings): Boolean;
var
i: Integer;
begin
Result := False;
DoMessage("InStrings, AStr="+AStr+", AStrings.Text="+AStrings.Text);
procedure TWebFilter.DoMessage(AMessage: string; ADebugOnly: Boolean = True);
begin
if Assigned(FOnMessage) then
FOnMessage(Self, AMessage, ADebugOnly);
end;
procedure TWebFilterThread.DoOnThrdMessage(Sender: TObject;
AMessage: string; ADebugOnly: Boolean = True);
begin
DoSyncMessage(AMessage, ADebugOnly);
end;
procedure TWebFilterThread.DoSyncMessage(AMessage: string; ADebugOnly: Boolean = True);
begin
FMessage := AMessage;
FDebugOnly := ADebugOnly;
Synchronize(DoMessage);
end;
procedure TWebFilterThread.DoMessage;
begin
if Assigned(FOnThrdMessage) then
FOnThrdMessage(Self, FMessage, FDebugOnly);
end;
procedure TThreadedWebFilter.DoOnThrdMessage(Sender: TObject;
AMessage: string; ADebugOnly: Boolean = True);
begin
if Assigned(FOnMessage) then
FOnMessage(Sender, AMessage, ADebugOnly);
end;
procedure TweClientMessengerService.DoOnWebFilterMessage(Sender: TObject;
AMessage: string; ADebugOnly: Boolean = True);
begin
AddLog("WebFilter, DoOnMessage: "+AMessage, ADebugOnly);
end;
procedure TweClientMessengerService.AddLog(AStr: string; ADebugOnly: Boolean = True);
begin
if FDebugMode then
try
WriteLog(AStr, FweFolders.dirCurrent + "weClientMessengerLog_DEBUG.txt");
except
end;
end;
я в нужном месте ищу баг? что может значить данный AV в ntdll.dll RtlLeaveCriticalSection ? Критич. секция не срабатывает почему-то или дело в чем-то другом?
← →
istok (2011-03-16 22:47) [1]забыл добавить: в итоге в выводимом файле после эксепшена иногда остаются незавершенные строки или вообще случайные символы попадают..
← →
sniknik © (2011-03-16 22:58) [2]> этого кода разными потоками
почитай в хелпе про DateTimeToStr
← →
istok (2011-03-16 23:04) [3]я понимаю что она not thread-safe, но я ж критич секцию юзю. разве не спасает?
← →
sniknik © (2011-03-16 23:22) [4]> критич секцию
с основным потоком?
> разве не спасает?
ну как сказать, само по себе, без логики, это как спасательный круг дома, когда тонешь на море.
← →
istok (2011-03-16 23:30) [5]почему ж с основным.., судя по логам и значению GetCurrentThreadId, этот код вызывают разные потоки... значит и enter\leave делается разными потоками. нет?
← →
sniknik © (2011-03-16 23:57) [6]да, да, пусть у тебя 10 спасательных кругов, и ты их дома красиво по стенкам периодически развешиваешь... к чему это на море?
> я понимаю что она not thread-safe
а понимаешь почему?
← →
RWolf © (2011-03-16 23:59) [7]
> Метод InStrings через цепочку событий (синхронизируются)
> в итоге вызывает WriteLog:
но эврика-то указывает на эксепшен в InStrings, при чём тут WriteLog?
← →
istok (2011-03-17 00:07) [8]в InStrings eureka указывает на строку
> DoMessage("InStrings, AStr="+AStr+", AStrings.Text="+AStrings.
> Text);
код этого метода и последовательность событий описаны.. я не понимаю, что тут криминального, кроме того что всё сводится к записи в лог..
а без записи в лог (та же цепочка событий, только writelog не делается) эксепшен и не ловится.
← →
RWolf © (2011-03-17 00:12) [9]
> я не понимаю, что тут криминального
AStrings.Text, видимо.
← →
istok (2011-03-17 00:57) [10]хм.. логирование показывает что всё что касается класса TWebFilter, на который указывает eureka, идёт из одного потока..
а разные потоки пересекаются только в writelog, где и стоит cs...
можете подсказать, что есть RtlLeaveCriticalSection в ntdll.dl ? его как следствие вызывает моя критич. секция при leave или это могут быть еще какие-то не созданные мною cs ?
← →
Германн © (2011-03-17 02:37) [11]
> istok (17.03.11 00:57) [10]
Если Эврика лицензионная, рекомендую напрямую обратиться в суппорт Эврики. Помогут, чем смогут.
← →
sniknik © (2011-03-17 08:07) [12]> идёт из одного потока..
из основного? а изменения с ним ты синхронизируешь? особенно в случае с DateTimeToStr где его настройки для него (из за которых "not ...") меняются в недрах VCL... внезапно.
p.s. если это логер, то логичнее было бы вынести его самого/работу с файлом в поток, а не пытаться синхронизироваться со всеми. а данные на запись ему посылать в сообщении. ИМХО конечно.
← →
Anatoly Podgoretsky © (2011-03-17 09:08) [13]Ничего криминального, только аргумент равен NIL
Недавно был аналогичный вопрос, тоже предложили восспользоваться Еврикой или подобным, а на уточняющий вопрос, как это поможет в случае "Access violation at address 00000000. Read of address 00000000." благополучно умолчали.
← →
han_malign (2011-03-17 10:48) [14]
> аргумент равен NIL
if Assigned(FOn...) then FOn...(...);
- у автора делается честно, больше callback-ов там вроде не видать...
это к вопросу об:
> как это поможет в случае "Access violation at address 00000000
- раскрутка стека помогает(иногда) локализовать место, где надо искать вызов функции, в которой осуществляется выход за границу локальной(размещенной на стеке) структуры.
Причем 1-4 младших байта "at address" совпадает с тем, что за эту границу писалось...
← →
sniknik © (2011-03-17 12:08) [15]>> аргумент равен NIL
> if Assigned(FOn...) then FOn...(...);
> - у автора делается честно, больше callback-ов там вроде не видать...
это к вопросу об:
это не аргумент, это проверка метода обработчика, аргумент это FOn...(...); здесь.
← →
sniknik © (2011-03-17 12:09) [16]> FOn...(...здесь...);
← →
istok (2011-03-17 14:21) [17]пока пришел к выводу что не синхронизировался DoMessage, он потом вызывает методы\события которые синхронятся через synchronize и естественно в writelog всё что идет по этому пути выдаёт один threadid
значит причина несинхрона где-то ДО этого..
поставлю секции на DoMessage, и ряд общих методов для потоков его вызывающих.. когда добавил вывод threadid в DoMessage, то увидел что разные threadid выводятся..
я уже запутсля в понимании того, что можно делать потокам без синхрона, а что нельзя... vcl-то понятно что низя, но тут одни переменные, часто tstringlist.. причем локальные... есть tstringlist у одного потока, есть у другого.. они выводят их через domessage на печать, передавая параметром tstringlist.text, а синхрон идёт уже после этого вызова.. криминально?
но даже если tstringlist переменная есть глобальная, доступная всем потокам - _ЧИТАТЬ_ одновременно всем можно или синхронить надо??
stringlist безусловно непотокобезопасен при записи, но если речь о чтении, то как?
← →
istok (2011-03-17 14:36) [18]кажется я всё понял..
там разных потоков быть и не должно было (на уровне видимости из domessage), а они есть из-за пары несинхроненных вызовов методов этого потока из других потоков... и получаются уже непонятные последствия, т.к. там много чего начинает юзится общего для нескольких потоков..
← →
Anatoly Podgoretsky © (2011-03-17 14:41) [19]> istok (17.03.2011 14:21:17) [17]
> stringlist безусловно непотокобезопасен при записи, но если речь о чтении,
> то как?
А как же тогда там записи оказались?
← →
istok (2011-03-17 14:49) [20]
> А как же тогда там записи оказались?
-если пишет в tstrings только один поток, а читают несколько.. то ок или нет?
(вопрос больше теоретический)
практическая часть свелась к следующему:
есть method1 в thread1 и method2 в thread2.
насколько я вижу, если method1 (из-под thread1) вызывает method2, то method2 выполняется в контексте thread1.
как сделать так, чтобы method1 (из-под thread1) вызывал method2 таким образом, чтобы method2 выполнялся в контексте thread2 ?
← →
Anatoly Podgoretsky © (2011-03-17 15:05) [21]> istok (17.03.2011 14:49:20) [20]
Теоритичекий говоришь?
Пусть было "Мама мыла раму" и в некоторый момент раму заменили на папу. Вот
и разрушение.
Так что требуется синхронизация или ThreadList
← →
sniknik © (2011-03-17 19:41) [22]> -если пишет в tstrings только один поток, а читают несколько.. то ок или нет?
блин, прямо мучения латентного голубого, типа "ну один раз не п. это понятно, но вот если только с одним, любимым, это же не считается... ведь правда? ок, или нет?"
по справке того же DateTimeToStr (для которого "понятно, что not thread-safe") которая не безопасна, и только потому что основной поток, один!, в используемые ей данные что то пишет.
если бы это "не считалось", то весь VCL тут же стал бы потоко безопасным, наполовину, для чтения. что не так.
> как сделать так, чтобы method1 (из-под thread1) вызывал method2 таким образом, чтобы method2 выполнялся в контексте thread2 ?
никак, код всегда работает в контексте того потока в котором вызывается. но можно -
> а данные на запись ему посылать в сообщении. ИМХО конечно.
← →
Дмитрий Белькевич (2011-03-17 21:17) [23]Закоменть подозрительный кусок - DateTimeToStr, либо еще что-то. Поможет - значит там проблему нужно искать. Нет - значит еще что-то.
← →
Loginov Dmitry © (2011-03-17 23:19) [24]
> Критич. секция не срабатывает почему-то или дело в чем-то
> другом?
Критическая секция - самый примитивный объект синхронизации. Он не глючит. Естественно, критическая секция должна быть создана (проинициализирована) до использования. А вот если ее не проинициализировать, то можно нарваться на какие угодно проблемы :)
Насчет "потоконебезопасности" DateTimeToStr. Здесь подразумевается, что результат работы данной функции может оказаться неожиданным, т.к. переменная, определяющая формат перевода даты в строку является глобальной, а значит теоретически изменить ее может параллельно выполняющийся код в любой момент времени. Привести к AV она не может. Не так давно где-то это обсуждалось.
← →
han_malign (2011-03-18 14:01) [25]
> > FOn...(...здесь...);
- а at address 00000000 - здесь(...) - потому что это адрес инструкции - а не параметра, и даже не ссылки на экземпляр класса...
Такая ситуация может возникать только в двух случаях:
1. при параметризованном переходе (call [], jmp [])
2. (для x86) при выходе из процедуры(ret) с запоротой точкой возврата
← →
sniknik © (2011-03-18 14:11) [26]> и даже не ссылки на экземпляр класса...
> function TWebFilter.InStrings(AStr: string; AStrings: TStrings): Boolean;
← →
han_malign (2011-03-18 15:22) [27]
> > function TWebFilter.InStrings(AStr: string; AStrings: TStrings): Boolean;program av;
{$APPTYPE CONSOLE}
uses Classes, SysUtils;
procedure _fail(sl: TStrings);
begin
Writeln(sl.Text);
end;
begin
try
_fail(nil);
except
on E: Exception do Writeln(E.Message);
end;
sl:= TStrings.Create;
try
_fail(sl);
except
on E: Exception do Writeln(E.Message + " at " + IntToHex(Cardinal(ExceptAddr), 8));
end;
sl.Free;
end.
---------Access violation at address 004126CB in module "av.exe". Read of address 00000000
Abstract Error at 0040AEEF
- что я делаю не так?
Если что - то(в отличие от плюсов) "в абстрактном VMT[]" лежит @_AbstractError, а не nil...
← →
RWolf © (2011-03-18 15:26) [28]
> [27]
переменная sl не объявлена.
← →
han_malign (2011-03-18 15:36) [29]
> sl не объявлена.
- сначала только nil отработал, а после отработки AbstractError - лень было все заново копировать... и инкрементальное обновление сбойнуло :))
← →
sniknik © (2011-03-18 15:55) [30]> - что я делаю не так?
теоретизируешь и вносишь сумятицу в абсолютно, кристально, ясную ситуацию - есть "дырка"? закрыть!
указаны уже две. а автор до сих пор "менжуется" - считается ли "дырка" "дыркой" если, во первых очень хочется "чтобы не считалось", о во вторых тут еще "опровергатели" разные смуту вносят, говорят что "этого" от "этого" быть не может.
> "в абстрактном VMT[]" лежит @_AbstractError, а не nil...
а ты вообще понимаешь о чем речь? при чем тут абстрактный базовый класс? он всегда указывается, как подходящий для "передач потомков".
а после следует вызов типа InStrings(Form.Memo1.Lines); (Lines объявлен абстрактный ну надо же) у которого есть события, а передается в поток...
вот о чем речь, а не о том что там используется абстрактный, и значит будет абстракт еррор, класс. VCL не потоко-безопасно, все, четко и ясно, вопрос закрыт, и никакие манипуляции с цифрами этого не изменят.
хотите еще "потрещать" на эту тему? с автором. он похоже желает чтобы его переубедили, что все у него ок, менять ничего не надо, и это все винда виновата...
← →
istok (2011-03-18 16:26) [31]вобщем я закрыл дырки в виде пары вызовов методов потока twebfilter другими потоками с помощью критич. секций и всё стало ок.
т.е. в методы типа twebfilter.InStrings реально входили несколько потоков без синхронизации.
а прелесть в том, что без логирования не юзается tstrings в паре мест и соответственно не возникает ошибки - оптимизация компиляции или что тут причина "невылета" ошибки мне не понять, да и не важно)
всем спасибо за помощь!
← →
han_malign (2011-03-18 16:51) [32]
> следует вызов типа InStrings(Form.Memo1.Lines);
> VCL не потоко-безопасно
- при чтении из неконсистентного композитного объекта, может возникнуть AV чтения - не разрушающее ни кучи, ни стека... При этом at address - ну никак не будет нулевым.
А говорил я - не `что "этого" от "этого" быть не может`, а что если верить Эврике, и в том случае, если повезло с адекватностью снимка стека - в методе CheckForBlockedUrl, или в каком то методе ниже по списку лога, надо искать вызов вложенной функции в которой разрушается стек...
Этим я всего лишь отвечал АПП - что Эврика в некоторых случаях может сузить область поиска "странных ошибок", если ума хватит...
DIXI
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.06.26;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.008 c