Есть такая обёртка для подключения:
int Connect(int &sock, addrinfo *target, string host, string port, bool udp = false){
if (sock > 0){closesocket(sock);}
addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = 0;
hints.ai_family = AF_INET;
hints.ai_socktype = udp?SOCK_DGRAM:SOCK_STREAM;
hints.ai_protocol = udp?IPPROTO_UDP:IPPROTO_TCP;
if (getaddrinfo(host.c_str(),port.c_str(),&hints,&target) != 0){return -1;}
if ((sock = socket(target->ai_family, target->ai_socktype, target->ai_protocol)) == -1){return -1;}
return connect(sock, target->ai_addr, target->ai_addrlen); // free addrinfo after use
}
Почему при такой конструкции приложение завершается с ошибкой на sendto (даже try/catch не работает):
addrinfo *target;
int udp_sock;
int error = Connect(udp_sock, target, VoIP_Data.host, VoIP_Data.port, true);
// далее идёт краш...
int result = sendto(udp_sock, frame.c_str(), frame.size(), 0, target->ai_addr, target->ai_addrlen);
А при такой отправка работает (правда потом крашится на freeaddrinfo, но это не важно):
addrinfo target; // без указателя
int udp_sock;
// передаём адрес target
int error = Connect(udp_sock, &target, VoIP_Data.host, VoIP_Data.port, true);
int result = sendto(udp_sock, frame.c_str(), frame.size(), 0, target.ai_addr, target.ai_addrlen);
Хотелось бы использовать функцию-обёртку для подключения с возможностью использовать далее addrinfo как в первом случае, но не понятны причины краша.
PS: всё работает корректно если алгоритм функции подключения написать прямо в main без отдельной функции.
Логично, что оно падает. Внутри функции Connect Вы берете адрес &target - но это адрес переменной на стеке. После выхода с функции она теряется, а оригинальная переменная target продолжает показывать туда, куда и раньше - в неизвестные дали (потому что нужно переменную инициализировать, в данном случае nullptr, тогда проблема быстро бы всплыла).
Так как target показывает неведомо куда, то другие функции, которые ее используют, ведут себя непредсказуемо.
Как исправить.
Объявляем так
addrinfo *target = nullptr;
сигнатуру функции Connect пишем так
int Connect(int &sock, addrinfo **target, string host, string port, bool udp = false)
вызываем так
int error = Connect(udp_sock, &target, VoIP_Data.host, VoIP_Data.port, true);
и в остальных местах поправить соответстующее. (подсказка (*target)->ai_addr).
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости