Segmentation fault при использовании структуры addrinfo в sendto

303
09 ноября 2017, 06:26

Есть такая обёртка для подключения:

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 без отдельной функции.

Answer 1

Логично, что оно падает. Внутри функции 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).

READ ALSO
Чтение из COM порта С++

Чтение из COM порта С++

Есть такой код:

353
C++ DLL библиотеки

C++ DLL библиотеки

Всем здравствуйтеНедавно я решил создать собственную динамически подключаемую библиотеку или иными словами dll

456
Перенаправление вывода в файл

Перенаправление вывода в файл

Скажите, пожалуйста, как внутри C++ программы можно перенаправить весь вывод в файл?

400
Редактирование кода для массива [требует правки]

Редактирование кода для массива [требует правки]

Не могу исправить ошибкипомогите кто то с кодом,позязязя:3

267