Падает *.Exe x64

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Падает *.Exe x64

Сообщение myles » 09.03.2012 20:36:15

Win 7 x64, lazarus 0.9.30/2.4.4

Предистория: была написана программка (консольная), довольно большая, запутанная и многопоточная.
Писал для делфи 7, возникла необходимость откомпилить под 64 бита, для чего и был использован лазарус. Откампилил (все использованные структуры и размеры переменных выровнены и тд). В целом - работает, но не непонятных обстоятельствах (по наблюдениям) когда паралельно начинают два потока что-то делать - все просто падает (программа завершается) либо вылазит ошибка SIGSEGV но окно местного отладочника вообще ничего не дает, могу только регистры посмотреть, даже заглянуть в дамп не могу - что же там происходит.

И такие действия я заметил на казалось бы самых безобидных операциях (во втором просто кручу циклы типа ReadDirectoryChangesW и при копировании файлов в эту папку прога вылетает). Я даже убрал все полезные действия, но все равно с Н-ноый попытки копирования удается получить падение.

Что плохо - то что на 32 битах она работает стабильно - рядом компилишь делфи32 и в путь, все ок. То есть я уверен что потоки засинхроонизированны и тд. Сделал отладку шагов в файл (тоже синхронизация, все дела). И закономерности не обнаружил, т.е. паралельно скидывают лог два потока и "последняя" запись может быть хоть того хоть того потока и всегда разная. То есть какая-то неведомая сила вырубает его.

Все дело запускаю под windbg и вирт. машину. Дак вот, этот отладочник так не же ловит исключение и соотв. программа просто "падает" - но предварительно появляется окно "отладить программу, завершить" и еще что-то такое (запускаю конечно в этом случае не из среды, а просто двойным кликом).

Еще прикол, что если где-то в начале проги поставить int 3 то windbg ловит это (при запуске дв. кликом), а вот эксепшн почему-то пропускает.

Вопрос: как отловить исключение?

Отладочник меня отправляет (не всегда) на кусок памяти (раздизасмил, опыт есть достаточный), но вообще как-будто не причем).
myles
незнакомец
 
Сообщения: 8
Зарегистрирован: 09.03.2012 20:12:15

Re: Падает *.Exe x64

Сообщение Максим » 09.03.2012 21:48:23

myles писал(а):довольно большая, запутанная и многопоточная.

Вот здесь и ответ. Ставлю на косяки при работе с указателями.
Аватара пользователя
Максим
энтузиаст
 
Сообщения: 599
Зарегистрирован: 27.07.2007 01:51:43
Откуда: Москва

Re: Падает *.Exe x64

Сообщение myles » 09.03.2012 22:30:11

Указатели я первым делом проверил, и действия которые приводят к падениям - ну упростил до простейшего Writeln (+ синхронизация конечно)...

Были бы указатели - то отваливалось бы всегда в каком-то одном месте, а тут - где повезет, даже закономерность не могу отследить...

Интересует, как с помощью штатного отладчика вообще хоть что-то сделать? И понять, что это он "бажит"...
myles
незнакомец
 
Сообщения: 8
Зарегистрирован: 09.03.2012 20:12:15

Re: Падает *.Exe x64

Сообщение Ism » 09.03.2012 22:33:29

Откомпилируйте с heaptrc
Думаю при падении он расскажет много интересного в консоль , а вообще http://wiki.lazarus.freepascal.org/profiling/ru
http://wiki.lazarus.freepascal.org/Mult ... utorial/ru
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Падает *.Exe x64

Сообщение Максим » 09.03.2012 22:53:43

myles писал(а):Были бы указатели - то отваливалось бы всегда в каком-то одном месте

Ну если вы так говорите, тогда да, конечно. :mrgreen:
Аватара пользователя
Максим
энтузиаст
 
Сообщения: 599
Зарегистрирован: 27.07.2007 01:51:43
Откуда: Москва

Re: Падает *.Exe x64

Сообщение Ism » 09.03.2012 23:58:26

Падать может изза некорректных математических операций, это достаточно тонкий вопрос, на этом форуме подобное обсуждалось, точнее странные последствия вычислений, правда тему не помню. При переходе на 64 бит вполне может нарушиться заполнение какой либо переменной
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Падает *.Exe x64

Сообщение myles » 10.03.2012 10:49:36

Ism, спасибо, посмотрел - то что нужно, буду проверять..

И всем остальным тоже спасибо, но проблема пока не решена.

Добавлено спустя 1 час 45 минут 57 секунд:
Упростил все до минимума:
работаю 2 потока:
первый - просто мониторит появление новых файлов (и выводит в файл)
второй - по циклу гоняет пакеты по сети (через сокеты)... Простейший запрос, простейший ответ (никакая полезная нагрузка не выполняется, чисто NOOP)

В момент, когда начинаю активно копировать по папке файлы (ReadDirectoryChangesW) то получаю падение. Теперь в отладочнике у меня пишется имя той процедуры (или функции) fpc_popaddrstack.
Но что это такое и почему она появилась.... Большой вопрос.

Если гонять эти два потока по отдельности друг от друга - то все ок работает.
Общего они ничего не юзают, пишут логи в разный файл...
myles
незнакомец
 
Сообщения: 8
Зарегистрирован: 09.03.2012 20:12:15

Re: Падает *.Exe x64

Сообщение Ism » 10.03.2012 14:23:53

Если б исходный код был было б интересней.
А не могут 2 потока обратиться к одному и тому же файлу ? Если обработки ошибок нет , то все может быть

первый - просто мониторит появление новых файлов (и выводит в файл)


Чтоб второй поток мог его использовать надо делать flush и освобождать файл

Если гонять эти два потока по отдельности друг от друга - то все ок работает.


Значит эти потоки както связаны
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Падает *.Exe x64

Сообщение alexey38 » 10.03.2012 14:35:48

В потоках могут вызываться потоко-небезопасные функции, которые где-то внутри FCP/LAZARUS пересекаются на общих ресурсах (переменных и т.п.).
В Delphi, например, потоко-небезопасный VCL, поэтому обращение к компонентам формы, application, application.ProcessMessage и др, даже при чтении (не отображение) может вызывать конфликты.

Вполне возможно, что x86 и x64 написаны немного по разному в части библиотек, что не вызывало конфликта в 32, может вызывать в 64.
alexey38
долгожитель
 
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Re: Падает *.Exe x64

Сообщение myles » 10.03.2012 14:49:08

Ребята, похоже что проблема решена. Суть:

У меня была написана функция типа

Код: Выделить всё
procedure Writeln1(s:string);
begin
WaitForSingleObject(SincEvent, 3000);
                    Writeln(s);
ReleaseSemaphore(SincEvent, 1, nil);
end;

И другая - по выводу информации в файл (я их юзал для отладки).
Юзал я их примерно так:
Writeln1('somestring '+inttostr(ID));

И так далее, то есть были операции s:=s1+s2;
Так или иначе происходило сложение строк - чтобы итоговая строка была передана параметром.

Здесь я прочитал что обработчик fpc_popaddrstack срабатывает в try except и что Лазарус сам в некоторых случаях может ставить его, например при сложении строк.
http://www.mombu.com/programming/programming/t-setjmplongjmp-causing-stack-corruption-685001.html

Видать где-то в недрах строка1+строка2 юзается что-то такое, что требует бережного отношения типа как с VCL с потоков.

Закомментировал все свои выводы в файл и в консоль - повторить крах мне пока не удалось!
myles
незнакомец
 
Сообщения: 8
Зарегистрирован: 09.03.2012 20:12:15

Re: Падает *.Exe x64

Сообщение Ism » 10.03.2012 15:22:51

так складывайте строки в локальную переменную и только потом готовую строку кидайте на вывод
Writeln1(str);
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Падает *.Exe x64

Сообщение alexey38 » 10.03.2012 17:14:06

myles писал(а):Ребята, похоже что проблема решена. Суть:
И так далее, то есть были операции s:=s1+s2;
Так или иначе происходило сложение строк - чтобы итоговая строка была передана параметром.
Видать где-то в недрах строка1+строка2 юзается что-то такое, что требует бережного отношения типа как с VCL с потоков.
Закомментировал все свои выводы в файл и в консоль - повторить крах мне пока не удалось!


Если это так, то это баг. Операции со строками уж точно должны быть потоко-безопасны, иначе потоки просто бесполезны.

Добавлено спустя 4 минуты 39 секунд:
myles писал(а):У меня была написана функция типа
Код: Выделить всё
procedure Writeln1(s:string);
begin
WaitForSingleObject(SincEvent, 3000);
                    Writeln(s);
ReleaseSemaphore(SincEvent, 1, nil);
end;



Вопрос, а объект ядра используемый для синхронизации: Event или Semaphore?
А то имя дискриптора содержит Event, а освобождаете его семафором. Тут либо ошибка (в x86 могло и работать, а в x64 другое API системы), либо некорректное наименование переменной (ненаглядный код).
alexey38
долгожитель
 
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Re: Падает *.Exe x64

Сообщение myles » 10.03.2012 18:02:05

Вопрос, а объект ядра используемый для синхронизации: Event или Semaphore?

Хорошее замечание, юзаю конечно семафор:
Код: Выделить всё
SincEvent:=CreateSemaphoreA(nil,1,1,nil); 


Если кому-то понадобится операции со строками - советую юзать lstrcpy и подобные. За полчаса можно написать библиотеку с динамическим выделением памяти под строки, там будут свои (без ограничений длины) lstrcpy, cat и ид...
myles
незнакомец
 
Сообщения: 8
Зарегистрирован: 09.03.2012 20:12:15


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: xchgeaxeax и гости: 241

Рейтинг@Mail.ru