我试图找出如何修复这些内存泄漏,我是在运行这个程序时,与瓦兰。泄漏发生在nShell_client_main中的两个分配中。但我不知道怎么才能把他们放出来。
我试图在nShell_Connect上释放他们,但这导致libUV中止了程序。我尝试在nShell_client_main结束时释放它们,但是在关闭循环时会出现读/写错误。有人知道我该怎么关闭这些手柄吗?我读过这,这让我开始了。但是,它已经过时了,因为uv_ip4_addr在最新版本中有一个不同的原型。
(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;
}这个断言发生在代码节选(摘自Joyent的Github上的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,但它不在公共标题中(而且可能不是正确的解决方案)。
发布于 2014-09-14 09:00:23
在调用关闭回调之前,libuv不会用句柄完成。那正是你可以释放手柄的时刻。
我看到您调用了uv_loop_close,但是没有检查返回值。如果仍然有挂起的句柄,它将返回UV_EBUSY,因此您应该检查它。
如果要关闭循环并关闭所有句柄,则需要执行以下操作:
uv_stop停止循环uv_walk并调用uv_closeuv_run运行循环,以便调用所有关闭回调,并且可以释放回调中的内存。uv_loop_close,它现在应该返回0发布于 2017-11-13 17:43:41
我终于想出了如何停止循环并清理所有的句柄。我创建了一堆句柄和SIGINT信号句柄:
uv_signal_t *sigint = new uv_signal_t;
uv_signal_init(uv_default_loop(), sigint);
uv_signal_start(sigint, on_sigint_received, SIGINT);当接收到SIGINT (按下控制台中的Ctrl+C)时,将调用on_sigint_received回调。on_sigint_received看起来像:
void on_sigint_received(uv_signal_t *handle, int signum)
{
int result = uv_loop_close(handle->loop);
if (result == UV_EBUSY)
{
uv_walk(handle->loop, on_uv_walk, NULL);
}
}它触发一个回调函数on_uv_walk。
void on_uv_walk(uv_handle_t* handle, void* arg)
{
uv_close(handle, on_uv_close);
}它试图关闭每个打开的libuv手柄。备注:,我不把uv_stop在uv_walk之前称为提到萨古尔。在调用on_sigint_received函数之后,libuv循环继续执行,并在下一次迭代中为每个打开的句柄调用on_uv_close。如果调用uv_stop函数,则不会调用on_uv_close回调。
void on_uv_close(uv_handle_t* handle)
{
if (handle != NULL)
{
delete handle;
}
}之后,libuv没有打开句柄并完成循环(从uv_run退出):
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
int result = uv_loop_close(uv_default_loop());
if (result)
{
cerr << "failed to close libuv loop: " << uv_err_name(result) << endl;
}
else
{
cout << "libuv loop is closed successfully!\n";
}发布于 2022-04-16 03:36:31
我喜欢康斯坦丁·加梅迪特给出的解决方案
不过,我确实遇到了一些问题。他的on_uv_close()函数以核心转储结束。此外,uv_signal_t变量导致val差利报告“绝对丢失”内存泄漏。
对于这两种情况,我使用他的代码进行修复。
void on_uv_walk(uv_handle_t* handle, void* arg) {
uv_close(handle, NULL);
}void on_sigint_received(uv_signal_t *handle, int signum) {
int result = uv_loop_close(handle->loop);
if(result == UV_EBUSY) {
uv_walk(handle->loop, on_uv_walk, NULL);
}
}int main(int argc, char *argv[]) {
uv_signal_t *sigint = new uv_signal_t;
uv_signal_init(uv_default_loop(), sigint);
uv_signal_start(sigint, on_sigint_received, SIGINT);
uv_loop_t* main_loop = uv_default_loop();
...
uv_run(main_loop, UV_RUN_DEFAULT));
uv_loop_close(uv_default_loop());
delete sigint;
return 0;
}https://stackoverflow.com/questions/25615340
复制相似问题