Решено: boost::intrusive_ptr (Странное поведение указателя)

Модератор: Модераторы разделов

Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Решено: boost::intrusive_ptr

Сообщение RasenHerz »

Пишу клиент для сетей dc++ и столкнулся с интересной проблемой, суть которой в следующем: при получении результатов поиска я обратил внимание что у файлов странно выглядит TTH:

Код: Выделить всё

PDIHWAQAAAAAB2IDCZ56NDG25O52X4JNTIA4V4Y
PDIHWAQAAAAAA7ZWUDYAF2WH4D2KEPRBNC4S3DY
PDIHWAQAAAAAAX5S4XKXKPMPEXMGBNEXGOHDGGQ
PDIHWAQAAAAABLIPPKLD2NNTKOJW44LM5MHU4VY
PDIHWAQAAAAAA34MMGC5GB2U4WN534E4XMVUPUI

Мало того что в хешах есть повторяющиеся последовательности, так еще при проверке другим клиентом выяснилось что таких хешей просто нет не у одного файла в сети. Я начал копать библиотеку dc++ и нашел код ответсвенный за отправку результата поиска в основное приложение:

Код: Выделить всё

SearchResultPtr sr(new SearchResult(user, type, slots, freeSlots, size,
            file, hubName, url, remoteIp, TTHValue(tth), Util::emptyString));// intrusive_ptr для SearchResult*

fire(SearchManagerListener::SR(), sr);

где fire определена как:

Код: Выделить всё

    template<typename T0, class T1>
    void fire(T0 type, const T1& p1) throw() {
        Lock l(listenerCS);
        tmp = listeners;
        for(ListenerIter i=tmp.begin(); i != tmp.end(); ++i ) {
            (*i)->on(type, p1);
        }
    }
    template<typename T0, class T1>
    void fire(T0 type, T1& p1) throw() {
        Lock l(listenerCS);
        tmp = listeners;
        for(ListenerIter i=tmp.begin(); i != tmp.end(); ++i ) {
            (*i)->on(type, p1);
        }
    }

Добавив отладочный вывод в библиотеку:

Код: Выделить всё

SearchResultPtr sr(new SearchResult(user, type, slots, freeSlots, size,
            file, hubName, url, remoteIp, TTHValue(tth), Util::emptyString));
printf("%s\n", sr->getTTH().toBase32().c_str());
fire(SearchManagerListener::SR(), sr);
printf("%s\n", sr->getTTH().toBase32().c_str());

Я убедился, во-первых, что в dc++ хеш верный, во-вторых, что переменная sr не изменяется (оба раза распечатывается верный хеш), т.е. данные портятся уже в основном приложении, вот только ничего криминального я не делаю:

Код: Выделить всё

void SearchFrame::on(SearchManagerListener::SR, const dcpp::SearchResultPtr& aResult) throw() {
    printf("%s\n", aResult->getTTH().toBase32().c_str());//Печатает неверный хеш
}

Причем aResult.get() == rs.get() т.е. указатель тот же самый что и в библиотеке.
Больше всего удивило что идентичный код в том же LinuxDC++ отрабатывает без проблем.
В общем, ваши мысли по поводу происходящего, господа. Если будет нужно, то выложу весь исходный код клиента (вместе с библиотекой).

P.S. Единственная мысль которая приходит в голову: что-то не так с флагами компиляции.

UPD.
Собственно вот еще чуть более читабельный вывод (SM - Search Manager (ядро), SF - Search Frame (клиент), и адрес элемента, хранящегося в intrusive_ptr):

Код: Выделить всё

{
        SM: 0x3909fc0 : HP5Y2X2C4YCKYCZAWQ32NW3XTQINLDPJFOQO3FY  //До вызова fire
        SF: 0x3909fc0 : 5BU7EAQAAAAAAO73RVPUFZQEVQFSBNBXU3NXPHA  //В обработчике fire, как видим TTH битый
        SM: 0x3909fc0 : HP5Y2X2C4YCKYCZAWQ32NW3XTQINLDPJFOQO3FY  //После выхода из обработчика
}
{
        SM: 0x3909fc0 : UBPZ7WBSQCFAEO7JHUQB7KANJNXHCD7COS6UHTA
        SF: 0x3909fc0 : 5BU7EAQAAAAABIC7T7MDFAEKAI56SPJAD6UA2SY
        SM: 0x3909fc0 : UBPZ7WBSQCFAEO7JHUQB7KANJNXHCD7COS6UHTA
}
{
        SM: 0x3909fc0 : N3ROD2UC47PQ4LP5DTTGBK3U3PDYXV4VZAD24TQ
        SF: 0x3909fc0 : 5BU7EAQAAAAAA3XC4HVIFZ67BYW72HHGMCVXJWY
        SM: 0x3909fc0 : N3ROD2UC47PQ4LP5DTTGBK3U3PDYXV4VZAD24TQ
}
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Решено: boost::intrusive_ptr

Сообщение RasenHerz »

У проблемы оказалось неожиданное решение: в dc++ есть есть переменные с названием slots (данное слово зарезервировано библиотекой Qt), в общем, весь бардак из-за этого.

Тему просьба закрыть.
Спасибо сказали: