| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Системное программирование и WinAPI > Потокозащищенность объектов |
| Автор: orlangur86 17.7.2008, 11:01 |
| Доброго времени суток всем форумчанам! Может быть данная тема уже поднималась и на форуме уже есть ответы на мои вопросы - что ж, тогда прошу простить, плохо искал (искал - это факт, но может не по тем ключевым словам) и был бы благодарен за ссылку на соответствующую ветку форума. Собственно проблема. Существует класс (пусть будет класс А) для работы в сети (ну скажем фтп-клиент), есть другой класс ( класс Б), который использует вышеуказаный сетевой компонент в своих целях. есть необходимость работы класса Б паралельно. Т.е. необходимо использовать потоки. Потоки вначале были реализованы на базе класса QThread (Qt lib) в виде: класс Б наследует от QThread и реализует метод обработки, за тем на базе того же QThread но это уже был отдельный класс, которому передавался указатель на Б, и тот уже при запуске вызывал обработку Б. Так же пробовал реализовать на базе Thread из библиотеки POCO (portable components). Создание объектов потока и класса Б происходит следующим образом. в основной программе: 1) обрабатывается командная строка 2) определяется число необходимых потоков 3) в цикле происходит: - создание объекта Б (динамически через new) - в конструкторе Б происходит создание объекта А (так же через new) и указатель на А сохраняется как private член класса (не static) - прочие настройки (не существенные для данного вопроса) - создание объекта потока с передачей в конструктор в качестве параметра, указатель на Б - запуск потока 4) join для всех потоков. Предполагается, что каждый поток пользуется своей копией Б, и своей копией А. Проблема возникает в том, что судя по логам, которые записываются при обращении к методам объекта класса А, этот объект вызывается как из родного потока, для которого он был создан, так и из чужих потоков, что недопустимо и в результате получается полный бред без всякой логики работы. Теперь вопрос. Как такое возможно, чтоб потоки вдруг получали доступ к памяти, по большому счету, указатель на которую они вообще знать не должны? Могу предположить, что при переключении контекстов потоков значения членов класса не меняются чтоль? так это как-то глупо... или я чего-то не знаю... помогите советом, кто может! заранее благодарю |
| Автор: Lycifer 17.7.2008, 11:20 |
| ТЫ используешь одну и туже память(у тебя должен быть кон7структор копирывания) |
| Автор: EnergoHokum 17.7.2008, 11:37 |
| Опиши подробнее, как ты формируешь логи. Кажется мне, всё дело в них. |
| Автор: orlangur86 17.7.2008, 11:56 |
| Lycifer, это как же я использую одну и ту же память если в тестовом отладочном варианте для 3-х потоков я создаю 3 объекта класса Б (как я уже писал при помощи new) и в конструкторе каждого объекта Б вызывается конструктор А (так же при помощи new) EnergoHokum, логи формируются следующим образом: в отладочном варианте и конструктор класса А и конструктор класса Б принимает доп параметр - число (ну в частности просто порядковый номер потока от 0 до 2 в отладочном случае) в конструкторе А создается файл (при помощи std::fstream класса) с именем some_name_<число которое передано в конструктор>.log при выполнении какого-либо метода А в лог записывается следующая информация: <число для отладки> <this приведеное к unsigned> <GetCurrentThreadId()> ну инфа по методу всякая и вот что число для отладки, что this имеют одно и то же значение (ну логично в принципе), но вот ID потока разный. причем такой микс во всех 3-х потоках, во всех 3-х лог-файлах, которые создаются... я в замешательстве |
| Автор: orlangur86 17.7.2008, 12:42 | ||||||||
| конструкторы копирования для А и для Б нигде не исопльзуются. даже в неявном виде. в одном месте происходит создание Б при помощи new, и в одном месте происходит удаление Б та же фигня и для А Класс Б объявлен примерно так:
Вот его конструктор и деструктор
Создание потоков и передача в них данных: в последней переделке/реализации сделано через POCO (portable Components) и их реализацию потоков. т.е.
в main'е все происходит примерно следующим образом
примерно так. |
| Автор: Lazin 17.7.2008, 12:53 | ||
| похоже на то, что ты неправильно пишешь в лог... экземпляры В, при такой реализации будут разными... Добавлено @ 12:59 кстати объекты у тебя создаются в одном потоке, но методы run должны вызываться из разных потоков... если тебе нужно, что-бы объекты создавались в разных потоках, добавь код по созданию объекта в код самого потока, пускай поток сам управляет своими данными...
|
| Автор: orlangur86 17.7.2008, 13:01 | ||
хз...
ну и как я уже писал: GetCurrentThreadId() на этом месте встречаются 3 разных значения в разных строках лога |
| Автор: Lazin 17.7.2008, 13:02 | ||||
в main теперь все проще:
Добавлено через 2 минуты и 5 секунд
ты уверен что у тебя вызывается метод одного объекта из разных потоков, а не один и тот-же метод разных объектов из разных потоков |
| Автор: orlangur86 17.7.2008, 13:14 | ||||
ну да... дело в том, что отладочное число и адрес this для одного лог-файла - одни и те же, а вот ИД потоков разные на счет более простого кода в main - да, наверное так действительно проще, но и в моем варианте ничего противозаконного нету (это я к тому, что и там должны пахать нормально потоки... но не пашут...) |
| Автор: orlangur86 18.7.2008, 10:29 |
| Спасибо всем, кто откликнулся! Проблема как всегда в драйвере прямых рук )) Один из ресурсов, который передавался классу Б в момент его инициализации, не был ни продублирован для каждого потока отдельно, и не был потоко-безопасным |