Tôi đang cố gắng tìm hiểu cách khắc phục những rò rỉ bộ nhớ mà tôi nhận được khi chạy chương trình này với Valgrind. Các rò rỉ xảy ra với hai phân bổ trong nShell_client_main
. Nhưng tôi không phải là chắc chắn cách giải phóng chúng một cách chính xác.Đóng chốt libUV Xử lý chính xác
Tôi đã thử giải phóng chúng tại nShell_Connect, nhưng nó khiến libUV hủy bỏ chương trình. Tôi đã thử giải phóng chúng vào cuối nShell_client_main
, nhưng sau đó tôi nhận được lỗi đọc/ghi khi đóng vòng lặp. Có ai biết làm thế nào tôi phải đóng những tay cầm? Tôi đã đọc this, điều này khiến tôi bắt đầu. Tuy nhiên, nó đường nối out-date bởi vì uv_ip4_addr
có một nguyên mẫu khác nhau trong phiên bản mới nhất.
(nShell_main
là "entry" điểm)
#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;
}
Khẳng định đang xảy ra ở phần cuối của câu lệnh switch trong trích đoạn mã này (lấy từ trang libUV Joyent trên Github):
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);
}
Tôi có thể gọi uv__tcp_close
theo cách thủ công nhưng không nằm trong tiêu đề công khai (và có thể không phải là giải pháp phù hợp).
Nhắc đến tránh mã xem xét mã của bạn; cách bố trí các tham số chức năng của bạn không chính thống và thực sự kỳ lạ (và do đó khó đọc) - và cũng không hoàn toàn nhất quán. –
@JonathanLeffler yeah, tôi bắt đầu toàn bộ dự án viết các hàm dài được chia nhỏ như thế. Bây giờ tôi hơi hối tiếc, nhưng chưa có cơ hội viết lại tất cả. – tay10r