gpt4 book ai didi

正确关闭 libUV 句柄

转载 作者:太空狗 更新时间:2023-10-29 17:14:33 43 4
gpt4 key购买 nike

我正在尝试找出如何修复我在使用 Valgrind 运行此程序时遇到的这些内存泄漏。泄漏发生在 nShell_client_main 中的两个分配。但我不是确定如何正确释放它们。

我已经尝试在 nShell_Connect 中释放它们,但它导致 libUV 中止程序。我试过在 nShell_client_main 结束时释放它们,但随后在关闭循环时出现读/写错误。有谁知道我应该如何关闭这些句柄?我读过 this ,这让我开始了。但是,它已经过时了,因为 uv_ip4_addr 在最新版本中有不同的原型(prototype)。

(nShell_main 是“入口”点)

#include "nPort.h"
#include "nShell-main.h"

void nShell_Close(
uv_handle_t * term_handle
){
}

void nShell_Connect(uv_connect_t * term_handle, int status){
uv_close((uv_handle_t *) term_handle, 0);
}

nError * nShell_client_main(nShell * n_shell, uv_loop_t * n_shell_loop){

int uv_error = 0;

nError * n_error = 0;

uv_tcp_t * n_shell_socket = 0;
uv_connect_t * n_shell_connect = 0;

struct sockaddr_in dest_addr;

n_shell_socket = malloc(sizeof(uv_tcp_t));

if (!n_shell_socket){
// handle error
}

uv_error = uv_tcp_init(n_shell_loop, n_shell_socket);

if (uv_error){
// handle error
}

uv_error = uv_ip4_addr("127.0.0.1", NPORT, &dest_addr);

if (uv_error){
// handle error
}

n_shell_connect = malloc(sizeof(uv_connect_t));

if (!n_shell_connect){
// handle error
}

uv_error = uv_tcp_connect(n_shell_connect, n_shell_socket, (struct sockaddr *) &dest_addr, nShell_Connect);

if (uv_error){
// handle error
}

uv_error = uv_run(n_shell_loop, UV_RUN_DEFAULT);

if (uv_error){
// handle error
}

return 0;
}

nError * nShell_loop_main(nShell * n_shell){

int uv_error = 0;

nError * n_error = 0;

uv_loop_t * n_shell_loop = 0;

n_shell_loop = malloc(sizeof(uv_loop_t));

if (!n_shell_loop){
// handle error
}

uv_error = uv_loop_init(n_shell_loop);

if (uv_error){
// handle error
}

n_error = nShell_client_main(n_shell, n_shell_loop);

if (n_error){
// handle error
}

uv_loop_close(n_shell_loop);
free(n_shell_loop);

return 0;
}

断言发生在这段代码摘录中 switch 语句的末尾(取自 Github 上的 Joyent 的 libUV 页面):

void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));

handle->flags |= UV_CLOSING;
handle->close_cb = close_cb;

switch (handle->type) {
case UV_NAMED_PIPE:
uv__pipe_close((uv_pipe_t*)handle);
break;

case UV_TTY:
uv__stream_close((uv_stream_t*)handle);
break;

case UV_TCP:
uv__tcp_close((uv_tcp_t*)handle);
break;

case UV_UDP:
uv__udp_close((uv_udp_t*)handle);
break;

case UV_PREPARE:
uv__prepare_close((uv_prepare_t*)handle);
break;

case UV_CHECK:
uv__check_close((uv_check_t*)handle);
break;

case UV_IDLE:
uv__idle_close((uv_idle_t*)handle);
break;

case UV_ASYNC:
uv__async_close((uv_async_t*)handle);
break;

case UV_TIMER:
uv__timer_close((uv_timer_t*)handle);
break;

case UV_PROCESS:
uv__process_close((uv_process_t*)handle);
break;

case UV_FS_EVENT:
uv__fs_event_close((uv_fs_event_t*)handle);
break;

case UV_POLL:
uv__poll_close((uv_poll_t*)handle);
break;

case UV_FS_POLL:
uv__fs_poll_close((uv_fs_poll_t*)handle);
break;

case UV_SIGNAL:
uv__signal_close((uv_signal_t*) handle);
/* Signal handles may not be closed immediately. The signal code will */
/* itself close uv__make_close_pending whenever appropriate. */
return;

default:
assert(0); // assertion is happening here
}

uv__make_close_pending(handle);
}

我可以手动调用 uv__tcp_close,但它不在公共(public) header 中(而且可能不是正确的解决方案)。

最佳答案

libuv 在关闭回调被调用之前不会处理句柄。那正是您可以松开 Handlebars 的时刻。

我看到您调用了 uv_loop_close,但您没有检查返回值。如果仍有待处理的句柄,它将返回 UV_EBUSY,因此您应该检查一下。

如果要关闭循环并关闭所有句柄,需要执行以下操作:

  • 使用uv_stop停止循环
  • 使用uv_walk 并在所有未关闭的句柄上调用uv_close
  • 使用 uv_run 再次运行循环,以便调用所有关闭回调,您可以释放回调中的内存
  • 调用uv_loop_close,现在应该返回0

关于正确关闭 libUV 句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25615340/

43 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com