[offtop]nesco, кажется, что это не Этюд, а разработка схемы/компонента. Может отрежешь?[/offtop]
Этот топик читают: Гость
Ответов: 4641
Рейтинг: 334
|
|||
карма: 1 |
|
Разработчик
Ответов: 26229
Рейтинг: 2140
|
|||
Ravilr писал(а): а разработка схемы/компонента. Может отрежешь?Это обнаруженный баг, который необходимо прибить, или схемно, или компонентно, но отрежу обязательно По теме, лучше всего оставить старый компонент, но вынести массив в глобальные переменные класса, тогда под него память, по идее, должна выделяться только один раз, тк как под string память динамически выделяется при каждом чихе
|
|||
карма: 22 |
|
Ответов: 1841
Рейтинг: 369
|
|||
nesco писал(а): вынести массив в глобальные переменные классахм, вынес и вроде полёт нормальный (пока что)... p.s. оставлю висеть дальше, посмотрим. |
|||
карма: 1 |
|
Ответов: 3889
Рейтинг: 362
|
|||
nesco,
nesco писал(а): сам поток глючит с выделенной памтью+1 Я с самого начала говорю только то, что вижу физически, в регистрах процессора, на стеке и в памяти. А вижу я, что менеджер памяти мается дурью. Если выделять память вручную, работать с указателем на эту область, а потом вручную её подчищать, то проблем, скорее всего, не будет. А если всё доверять менеджеру памяти, то при многопоточности он по невыясненным причинам начинает путаться, где-то досадная редко вылезающая ошибка прокралась. В текущем потоке, который вылетел, дебаггером я вижу жёстко зафиксированную в адресном пространстве структуру переменных менеджера памяти, в которой прописаны недопустимые адреса за пределами 3 гигабайт. Кто их туда записал - загадка, при инициализации приложения там всё нормально (в пределах сегмента данных). Надо трассировать, трассировать... А учитывая многопоточность, мне, пожалуй, не хватит свободного времени - многопоточная трассировка - непростое и кропотливое дело. |
|||
карма: 1 |
|
Разработчик
Ответов: 26229
Рейтинг: 2140
|
|||
1nd1g0 писал(а): А учитывая многопоточность, мне, пожалуй, не хватит свободного времени - многопоточная трассировка - непростое и кропотливое делоА что творится при вынесении переменной в область глобальных переменных класса ![]() |
|||
карма: 22 |
|
Ответов: 3889
Рейтинг: 362
|
|||
nesco, боюсь, от меня будет толк только завтра, когда будет доступ к XP. Проверил, на WOW64 и современной многоядерной машине самый первый пример работает за счёт высокой производительности железа и ядра - успевает всё отработать до наступления следующего таймера. Если же таймер уменьшить, при паре-тройке срабатываний до завершения прошлых "циклов", вылетает точно так же, как на XP. Но дебаггер пока не доступен
![]() |
|||
карма: 1 |
|
Ответов: 131
Рейтинг: 15
|
|||
[flood]1nd1g0, Ни когда и ни кому не обещайте ни чего, а то
1nd1g0 писал(а): nesco, боюсь, от меня будет толк только завтра |
|||
карма: 0 |
|
Ответов: 3889
Рейтинг: 362
|
|||
nesco писал(а): А что творится при вынесении переменной в область глобальных переменных классаВынес. Это замаскировало баг в менеджере памяти для hiWinExec. Теперь вылетает в разных местах менеджер памяти для hiCharset ![]() Что-то мне подсказывает, что после маскировки уязвимых мест и тут, они обнаружатся и в hiStrList. И так - во всех компонентах, неявно использующих динамическое выделение памяти в этом "несчастливом" потоке. Переделывать все компоненты - нонсенс. Менеджер памяти тоже вряд ли кто-то будет исправлять, так что... ------------ Дoбавленo в 08.42: Что интересно, если заменить в схеме WinExec на что-нибудь, вылеты в Charset прекращаются. То есть цепная реакция начинается именно с него. Что-то в нём портит структуру данных менеджера динамической памяти и дальше любая операция по удалению или выделению ячеек в контексте этого же потока приводит к фатальным ошибкам. Если же давать ему больше времени на исполнение вызванного приложения, то выполняется меньше его экземпляров и вероятность вылета обратно пропорциональна длине периода и производительности компьютера. Было подозрение, что более одного потока вызывают гарантированный сбой уже в самом начале отработки WinExec, при сокращении периода вызова до 200 мсек, потоков бывало более 50, пока не начинало вылетать. А при большем периоде иногда вылетает уже на 3-м. То есть какой-то этап WinExec гарантированно портит структуры менеджера памяти. При меньшем периоде успевает запуститься больше потоков, пока не доходит до этого этапа. При большем периоде до него доходит уже на первых нескольких. При одном потоке он сам себе не враг, так что до порчи памяти вообще не доходит. Что это за этап можно догадаться по тому, что один единственный tasklist в менеджере процессов зависает навечно, в гордом одиночестве. Программа падает, он так и останется невидимо висеть (ибо вывод его направлен был в поток нашего приложения). Если заменить его на несуществующую консольную команду, то всё равно вылетает, но ничего висеть не остаётся. WinExec с пустым полем FileName отрабатывает очень быстро и, естественно, не вылетает. ------------ Дoбавленo в 11.04: Есть мнение, что tasklist остаётся висеть потому, что не успел до конца отдать свой консольный вывод т.к. вызвавший его поток с WinExec вылетает раньше. |
|||
карма: 1 |
|
Разработчик
Ответов: 26229
Рейтинг: 2140
|
|||
А ты какую схему исследуешь
![]() Как ведет себя последня схема с уничтожением tasklist и повторным его запуском ![]() |
|||
карма: 22 |
|
Ответов: 3889
Рейтинг: 362
|
|||
Заменил на tasklist на ping localhost, не вылетает, в процессах висит один и тот же ping, потоков по таймеру сформировались сотни. Естественно, режим WinExec асинхронный (т.е. не менял его). Редкий, но меткий глюк.
Сейчас верну глобальную декларацию pBuffer обратно в функцию и посмотрю, не будет ли вылетать на ping (на несуществующих командах вылетает же). ------------ Дoбавленo в 11.33: nesco писал(а): Как ведет себя последня схема с уничтожением tasklist и повторным его запускомНа первый взгляд - не вылетает. Мнение, что при попытке запустить уже работающий процесс с консольным выводом происходит конфликт, портящий рабочие структуры менеджера памяти? Ещё мнение, что чем больше запускаемое выводит текста, тем выше вероятность вылета. Например, попытка запустить несуществующую команду приводит всего к одной строчке в консоль - "Данная команда не поддерживается. Воспользуйтесь параметром "x /?"." Но даже она иногда вызывает вылет, если выполнять по таймеру. Ping, наверное, вылетел бы, если бы выводил текст быстро, но он медленный (большой лаг между запуском и выводом) и (потому?) упорно не хочет вылетать. ------------ Дoбавленo в 11.43: Подтвердилось, стоило уменьшить таймаут у пинга до 1 мс, менеджер памяти вылетел сразу же, однако ping висеть не остался. Сейчас сделаю ему большой вывод - кол-во итераций подниму, посмотрю. |
|||
карма: 1 |
|
Разработчик
Ответов: 26229
Рейтинг: 2140
|
|||
Напрашивается вывод -- нефиг запускать повторно консольное приложение в асинхронном режиме, не уничтожив предыдущий экземпляр
|
|||
карма: 22 |
|
Ответов: 3889
Рейтинг: 362
|
|||
nesco, да, этот вывод с самого начала очевиден. Только надо добавить "по таймеру", т.е. в отдельном потоке. На цикле ничего не вылетает. С Thread сейчас попробую.
Мне было любопытно, что же портит работу менеджера памяти, потому и потратил столько времени на это. |
|||
карма: 1 |
|
Разработчик
Ответов: 26229
Рейтинг: 2140
|
|||
1nd1g0 писал(а): С Thread сейчас попробуюА зачем делать поток в потоке, дополнительный геморрой на голову ![]() 1nd1g0 писал(а): Только надо добавить "по таймеру"Совсем не обязательно, для всего пойдет, хуже не будет |
|||
карма: 22 |
|
Ответов: 3889
Рейтинг: 362
|
|||
nesco писал(а): поток в потокеШутить изволите? For -> Thread, а не Timer -> Thread. |
|||
карма: 1 |
|
Разработчик
Ответов: 26229
Рейтинг: 2140
|
|||
1nd1g0 писал(а): Шутить изволите? For -> Thread, а не Timer -> ThreadА причем тут тогда 1nd1g0 писал(а): С Thread сейчас попробуюНа это я и ответил nesco писал(а): зачем делать поток в потокеМне показалось, что речь шла о замене таймера на элемент Thread |
|||
карма: 22 |
|