#c #sockets #memory #memset
Вопрос:
src.cpp
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main(){
struct addrinfo hints, *servinfo;
memset(amp;hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, "1560", amp;hints, amp;servinfo);
freeaddrinfo(amp;hints);
}
Я использовал gdb, чтобы выяснить, где возникает ошибка, и она возникает в memset
, но когда я комментирую вызов freeaddrinfo (), он не выдает ошибок и работает!
Я использую ядро Ubuntu 20.04.2 5.8.0-55-generic
редактировать: как вы указали, что я должен предоставить freeaddrinfo список, предоставленный getaddrinfo, когда я передаю servinfo в freeaddrinfo, он выдает следующую ошибку
double free or corruption (out)
[1] 4123 abort (core dumped) ./a.out
редактировать 2: спасибо, при редактировании вопроса я забыл заменить amp;подсказки на servinfo и подумал, что я уже заменил его, извините за неубедительность, я заслуживаю каждого понижения за свою глупость.
Комментарии:
1. Вы могли бы попробовать использовать valgrind
Ответ №1:
freeaddrinfo
Функция ожидает указатель на список addrinfo
структур, созданных getaddrinfo
.
Указатель, который вы передаете, не относится к такому списку структур, так что это приведет к неопределенному поведению внутри функции
getaddrinfo
Функция , скорее всего, выделяет используемые структуры malloc
, и freeaddr
функция передает их free
.
Вы не можете передать указатель на free
то, что не было возвращено malloc
(или другой связанной функцией, такой как calloc
или realloc
).
Вы не выделяете динамически пространство для hints
. Вы размещаете его в стеке. Его не следует передавать freeaddrinfo
, должен быть только результат ( servinfo
в вашем случае).
Комментарии:
1. как вы указали, что я должен предоставить freeaddrinfo список, предоставленный getaddrinfo, когда я передаю servinfo в freeaddrinfo, он выдает двойную ошибку о свободе или повреждении 🙁
2. @HPSmash77 Просто не звони
freeaddrinfo(amp;hints)
? В качестве общей подсказки: всякий раз , когда вам нужно использовать оператор указателя на (или адрес)amp;
при вызове любой функции, содержащей терминfree
, вы должны воспринимать это как признак того, что вы делаете что-то не так.
Ответ №2:
freeaddrinfo(amp;hints);
Это ожидаемое поведение (в том смысле, что оно не определено; не в том смысле, что вы могли бы полагаться на это поведение). Вы можете передавать только структуру, созданную getaddrinfo
into freeaddrinfo
. Ты не творил amp;hints
с getaddrinfo
помощью . Не проходите hints
внутрь freeaddrinfo
.
Фиксированный пример:
addrinfo hints {
.ai_flags = AI_PASSIVE,
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
};
addrinfo* resu<
int err = getaddrinfo(nullptr, "12345", amp;hints, amp;result);
if (err) {
std::cout << "getaddrinfo: " << gai_strerror(err);
std::exit(EXIT_FAILURE);
} else {
// use it here
freeaddrinfo(result); // pay particular attention to this
}
Я заменил его на freeaddrinfo(servinfo);
Ваш новый пример все еще имеет freeaddrinfo(amp;hints)
, но также freeaddrinfo(servinfo)
. Если вы замените первое на второе, то вы звоните freeaddrinfo(servinfo)
дважды. Вы не можете использовать признанный недействительным servinfo
после его освобождения, в том числе передавать его во freeaddrinfo
второй раз. Применяются те же правила std::free
, что и в отношении .
Комментарии:
1. как вы указали, что я должен предоставить freeaddrinfo список, предоставленный getaddrinfo, когда я передаю servinfo в freeaddrinfo, он выдает двойную ошибку о свободе или повреждении 🙁
2. @HPSmash77 Вы должны удалить строку
freeaddrinfo(amp;hints);
3. Я заменил его на freeaddrinfo(servinfo); а затем он выдает ошибку, указанную мной в предыдущем комментарии
4. @HPSmash77 См.правку. Также смотрите мой пример.
5. о! извините, забыл это сделать при редактировании кода 🙁