c ++ массив новый символ [] с boost :: shared_array? - PullRequest
0 голосов
/ 28 декабря 2011

Обновлено

Будет ли работать эта строка кода:

boost::shared_array<struct sockaddr> addr(
    reinterpret_cast<struct sockaddr *>(
        (ipv6 ? new unsigned char [sizeof(struct sockaddr_in6)]
              : new unsigned char [sizeof(struct sockaddr_in)])
    )
);

Обратите внимание на два разных типа данных между распределением и типом, указанным в <template>.


Оригинальный вопрос был с boost :: shared_ptr

Будет ли работать эта строка кода:

boost::shared_ptr<struct sockaddr> addr(
    reinterpret_cast<struct sockaddr *>(
        (ipv6 ? new unsigned char [sizeof(struct sockaddr_in6)]
              : new unsigned char [sizeof(struct sockaddr_in)])
    )
);

Обратите внимание на два разных типа данных между распределением и типом, указанным в <template>.

Решение

boost::shared_array<unsigned char> address(new unsigned char [sizeof(sockaddr_in)]);

ПРИМЕЧАНИЕ. Используется тот же тип беззнакового символа с размером, точно равным необходимому.

и затем, когда я собираюсь использовать его:

bind(, (sockaddr*)address.get(), );

Ответы [ 3 ]

6 голосов
/ 28 декабря 2011

Это неверно.В какой-то момент умный указатель попытается сделать что-то вроде:

sockaddr* data;
// ...
delete data; // boom!

Ваш буфер необходимо удалить другим способом (с delete[], а не delete и через указатель правильного типа).

Взгляните на boost::shared_array, может быть, это то, что вам действительно нужно.


После ваших правок и комментариев

Можно использовать безопасное для типов решение:

typedef boost::shared_ptr<
     boost::variant<sockaddr_in,
                    sockaddr_in6>
     > sharedSockaddr;

// helper function for interaction with C
sockaddr* getSockaddr(sharedSockaddr addr) {

    struct printer : boost::static_visitor<>
    {
       sockaddr* out;

       void operator()(const sockaddr_in& t)
       {
          out = reinterpret_cast<sockaddr*>(&t);
       }

       void operator()(const sockaddr_in6& t)
       {
          out = reinterpret_cast<sockaddr*>(&t);
       }
    };

    printer p;
    boost::apply_visitor(p, *addr);
    return p.out;
}

Используйте sharedSockaddr s в своем коде и используйте getSockaddr всякий раз, когда вам нужно получить sockaddr* для перехода к C API.

3 голосов
/ 28 декабря 2011

Чтобы быть в безопасности, вы должны использовать пользовательское средство удаления, чтобы сделать reinterpret_cast возврат к исходному типу указателя перед удалением:

boost::shared_ptr<struct sockaddr> addr(
    reinterpret_cast<struct sockaddr *>(
        (ipv6 ? new unsigned char [sizeof(struct sockaddr_in6)]
              : new unsigned char [sizeof(struct sockaddr_in)])
    ),
    [](struct sockaddr* ptr) {
        delete[] reinterpret_cast<unsigned char*>(ptr);
    }
);

Если ваш компилятор не поддерживает лямбда-выражения, вы можетевместо этого используйте обычную функцию.

void delete_the_socket(struct sockaddr* ptr) {
    delete[] reinterpret_cast<unsigned char*>(ptr);
}
0 голосов
/ 28 декабря 2011

Почему бы вам не использовать оператор new () напрямую?

boost::shared_ptr<struct sockaddr> addr(
    ipv6 ? static_cast<struct sockaddr*>(::operator new(sizeof(struct sockaddr_in6)))
         : static_cast<struct sockaddr*>(::operator new(sizeof(struct sockaddr_in)))
);
...