использование memset и freeaddrinfo приводит к двойной ошибке «свободно» или » повреждено

#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. о! извините, забыл это сделать при редактировании кода 🙁