You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

libuv报错:未初始化流问题排查及代码求助

问题分析与修复方案

嘿,我一眼就瞅出你这问题的根源了——不是流没初始化,是TCP客户端对象的内存生命周期出问题啦!

为啥会触发这个断言?

看你SendData函数里的这段代码:

void SendData( uv_async_t*sd ) {
    uv_tcp_t client; // 划重点:这是个局部栈变量!
    uv_tcp_init(loop, &client);
    uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
    // ... 其他代码
    uv_tcp_connect(connect, &client, ..., OnConnectToServer);
}

uv_tcp_t client是SendData函数里的局部变量,当SendData执行完返回时,栈上的这个变量会被直接回收,内存变成无效状态。但uv_tcp_connect是异步操作,OnConnectToServer回调要到连接完成后才会执行,这时候你通过client->handle拿到的已经不是合法的uv_tcp_t对象了,uv_write检查流类型时自然就触发了断言错误。

怎么修复?

你得把客户端对象的内存分配到堆上,确保在回调执行时它还活着。我给你改了代码,还加了个自定义结构体把连接请求和客户端对象绑定在一起,方便回调里拿数据:

// 自定义结构体,把连接请求和客户端对象绑定
typedef struct {
    uv_connect_t connect_req;
    uv_tcp_t client;
} client_connect_t;

void OnConnectToServer(uv_connect_t *connect_req, int status) {
    if (status < 0) {
        // 连接失败,记得释放堆内存
        client_connect_t *client_conn = (client_connect_t*)connect_req->data;
        free(client_conn);
        return;
    }
    
    printf( "Client attempt write\n" );
    
    write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
    req->buf = uv_buf_init( (char*) malloc(1), 1 );
    (req->buf.base)[0] = '0';
    
    // 从connect_req的data字段拿到对应的客户端对象
    client_connect_t *client_conn = (client_connect_t*)connect_req->data;
    // 把uv_tcp_t转成uv_stream_t,这在libuv里是合法的继承转换
    uv_write((uv_write_t*) req, (uv_stream_t*)&client_conn->client, &req->buf, 1, OnWrite);
}

void SendData( uv_async_t*sd ) {
    // 给自定义结构体分配堆内存
    client_connect_t *client_conn = (client_connect_t*)malloc(sizeof(client_connect_t));
    if (!client_conn) return; // 内存分配失败直接返回
    
    uv_tcp_init(loop, &client_conn->client);
    // 把自定义结构体和connect_req绑定,方便回调里获取
    client_conn->connect_req.data = client_conn;
    
    struct sockaddr_in dest;
    uv_ip4_addr("192.168.20.3", PORT, &dest);
    uv_tcp_connect(&client_conn->connect_req, &client_conn->client, (const struct sockaddr*)&dest, OnConnectToServer);
}

额外提醒

  • 别忘了在OnWrite回调里也要释放write_req_t和buf的内存,还有后续客户端关闭时要释放client_connect_t的内存,别造成内存泄漏!
  • libuv里的uv_tcp_t是继承自uv_stream_t的,所以强制类型转换是安全的,这也是libuv官方推荐的用法。

内容的提问来源于stack exchange,提问作者dinner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:36:36