crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Работа с вектором STL
AD
  опции профиля:
сообщение 12.2.2009, 13:22
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Есть такая функция:
struct LOGRECORD
{
         int* param;     ///< массив параметров
         int* words;     ///< массив слов
        LOGRECORD(): param(0), words(0) {}

       /// any functions
};

std::vector<LOGRECORD> getLog() { return log; }

/// Функция в классе другого потока имеет след. строчку
vector<LOGRECORD> log = main_window -> getLog();

При некоторых обстоятельствах программа рушится на этой строке. В дебаггере выпадаю на строки
_DEBUG_ERROR("vector iterators incompatible");
            _SCL_SECURE_INVALID_ARGUMENT;

Есть предложения, как можно этого избежать? По всей видимости, это происходит, когда вектор log пустой, но почему он не дает проверить размер вектора функцией size() - для меня загадка. Буду благодарен за помощь.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
void*
  опции профиля:
сообщение 12.2.2009, 15:32
Сообщение #2


Программист-самоучка
***

Группа: Участник
Сообщений: 429
Регистрация: 4.6.2008
Пользователь №: 193

Спасибо сказали: 28 раз(а)




Репутация:   3  


std::vector<LOGRECORD> getLog() { return log; }

что за переменная вовращается? про нее ничего не сказано, откуда берется и т.п.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 12.2.2009, 16:18
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(void* @ 12.2.2009, 15:32) *
std::vector<LOGRECORD> getLog() { return log; }

что за переменная вовращается? про нее ничего не сказано, откуда берется и т.п.

Переменная log - вектор LOGRECORD. Переменная класс TLV. Заполняется при считывании лог-файлов.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kuler
  опции профиля:
сообщение 12.2.2009, 18:08
Сообщение #4


Танцор диско
***

Группа: Участник
Сообщений: 441
Регистрация: 11.9.2008
Из: Москва
Пользователь №: 289

Спасибо сказали: 6 раз(а)




Репутация:   -1  


попробуй какую нить критическую секцию
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 12.2.2009, 18:46
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(kuler @ 12.2.2009, 18:08) *
попробуй какую нить критическую секцию

Направление правильное.

Мне на форуме progz.ru/forum сказали следующее:
Цитата('Влад')
Ну, ты влетел!..
1. При каких именно "некоторых обстоятельствах" программа рушится? Попытайся уточнить.
2. У тебя идет некорректная работа с твоим логом в многопоточной программе. Навскидку, с ходу видны такие проблемы:
твоя функция getLog() пытается вернуть копию лога, существовавшего на момент ее вызова. Не факт, что это ей вообще удастся, вот возможный сценарий:
Поток 1 Поток 2
Вызов getLog().
Функция скопировала N первых
элементов, но еще не все!
И в этот момент диспетчер потоков переключает поток!
--------------------------------------------------------
Вызвана функция записи в лог.
Изменен лог с переаллокированием
памяти, все итераторы стали невалидными!
--------------------------------------------------------
Функция пытается продолжить
копирование, и тут-то ба-бах!!!
Используемые ею итераторы уже
невалидны. Все падает!Обрати внимание, что переключение потоков ОС может выполнить в любой момент по своему усмотрению.
3. Неизвестно, что происходит с указателями в исходном логе, когда они становятся невалидными. Обрати внимание, что они просто тупо копируются (поскольку это POD) в копию, возвращенную фунцией getLog(). На ровном месте ты можешь поиметь кучу проблем вплоть до расстрела совершенно случайной памяти.
Я бы порекомендовал в param и words использовать либо vector<int>, либо (с меньшими накладными расходами, хотя непонятно, существенно ли это в твоем случае) boost::shared_array или аналог. Ну или, на худой конец, определить для LOGRECORD конструктор копирования и оператор=.
4. Абсолютно необходим синхронизирующий объект. Для Win32/MFC это, видимо, CCriticalSection, для posix - pthread_mutex_t и т.п. Лучше всего завернуть этот синхронизирующий объект в "тонкий" класс.
5. Задумайся над семантикой функции getLog() - должна ли она возвращать копию текущего лога, как сейчас, или же ссылку на реальный лог (std::vector<LOGRECORD>& getLog() { return log; }), возможно, константную (const std::vector<LOGRECORD>& getLog() const { return log; })?


Осталось придумать, как правильно это реализовать!

Сообщение отредактировал AD - 12.2.2009, 18:48
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kuler
  опции профиля:
сообщение 12.2.2009, 19:06
Сообщение #6


Танцор диско
***

Группа: Участник
Сообщений: 441
Регистрация: 11.9.2008
Из: Москва
Пользователь №: 289

Спасибо сказали: 6 раз(а)




Репутация:   -1  


могу предложить лишь сделать евент, который когда горит значит ктото ведет работу с вектором и нужно ждать пока он не погаснет. Соответственно когда начинаешь чтото делать с вектором то его зажигаешь. Это не очень просто и не очень красиво, но по другом врядли получится.
vector<int> - не решит проблему
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 12.2.2009, 20:12
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(kuler @ 12.2.2009, 19:06) *
могу предложить лишь сделать евент, который когда горит значит ктото ведет работу с вектором и нужно ждать пока он не погаснет. Соответственно когда начинаешь чтото делать с вектором то его зажигаешь. Это не очень просто и не очень красиво, но по другом врядли получится.
vector<int> - не решит проблему

Причем здесь vector<int>? То, что ты предлагаешь, есть работа QMutex, QSemaphore! Он об этом же говорит. И первое решение, которое ты предложил, тоже имеет эту же цель.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kuler
  опции профиля:
сообщение 12.2.2009, 20:23
Сообщение #8


Танцор диско
***

Группа: Участник
Сообщений: 441
Регистрация: 11.9.2008
Из: Москва
Пользователь №: 289

Спасибо сказали: 6 раз(а)




Репутация:   -1  


Цитата(AD @ 12.2.2009, 20:12) *
Причем здесь vector<int>?

Я бы порекомендовал в param и words использовать либо vector<int>,
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 13.2.2009, 14:05
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Конкретно эту проблему решил. Поставив мьютекс. Вот так:
// in additional thread
main_window -> mutex.lock();
vector<LOGRECORD> log = main_window -> getLog();
main_window -> mutex.unlock();



// in main thread
const std::vector<LOGRECORD>& getLog() { return log; }

Теперь вопрос, как правильно заполнить. А то ничего не отображается и вектор пустой, почему-то. Но это отдельный вопрос!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 19:11