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

指针/对象失效求助:std::vector存储指针后多次调用失效

分析与解决方案:指针/对象失效问题

从你的代码和描述来看,指针失效的核心原因大概率是多线程环境下对std::vector的无同步访问,再加上可能的内存管理不规范,咱们一步步拆解:

一、最可能的根本原因:多线程数据竞争

你的Server->m_ClientGameState被多个接收线程同时访问(一个线程遍历读,另一个线程可能在执行push_back写),但std::vector本身不是线程安全的——当多个线程同时进行读和写操作时,会触发未定义行为,表现出来可能就是指针看似“失效”、程序崩溃或者数据乱码。

举个例子:当一个线程正在遍历vector时,另一个线程触发了push_back导致vector扩容,虽然vector里存的是对象指针(扩容不会销毁指针指向的对象),但遍历过程中的迭代器可能已经失效,或者vector的内部结构被破坏,导致你拿到的指针指向的内存状态异常。

二、其他潜在问题

  1. 裸指针的内存管理风险:你用new创建对象但没有对应的delete,不仅会内存泄漏,还可能在其他地方不小心释放了这些对象(比如某个线程误删),导致后续访问野指针。
  2. snprintf的缓冲区大小错误:你代码里用sizeof(Message.message().Server)作为目标缓冲区的大小,这是错误的——应该用GameState->Message.Server的实际大小,否则可能导致缓冲区溢出,破坏内存结构。
  3. 智能指针使用不当:如果你之前尝试智能指针时没有配合同步机制,或者误用了auto_ptr(已废弃),那同步问题没解决的话,指针失效的问题依然会存在。

三、修复方案

1. 给vector加线程同步锁

在Server类里添加一个互斥量,所有访问m_ClientGameState的操作(读、写、修改)都必须先加锁:

#include <mutex>

class Server {
    // ... 其他成员
    std::mutex m_GameStateMutex; // 保护m_ClientGameState的互斥量
    std::vector<std::unique_ptr<InGameState_t>> m_ClientGameState; // 改用unique_ptr管理内存
    // ...
};

2. 修改消息处理函数,确保线程安全

static void OnUpdateInGameState(Socket::Server* Server, int Client, const char* Data) {
    Messages::MessageUpdateInGameState Message(Data);

    // 用lock_guard自动管理锁,出作用域自动解锁,避免死锁
    std::lock_guard<std::mutex> lock(Server->m_GameStateMutex);

    for (auto& GameState : Server->m_ClientGameState) {
        if (!GameState) continue;
        if (GameState->Client == Client) {
            GameState->Message.InGame = Message.message().InGame;
            // 修正snprintf的缓冲区大小:用目标缓冲区的实际大小
            snprintf(GameState->Message.Server, sizeof(GameState->Message.Server), 
                     "%s", Message.message().Server);
            return;
        }
    }

    // 用emplace_back + make_unique替代new,更安全,避免内存泄漏
    Server->m_ClientGameState.emplace_back(
        std::make_unique<InGameState_t>(Client, Message.message())
    );
}

3. 额外注意事项

  • 确保所有访问m_ClientGameState的代码(比如其他线程的erase、clear操作)都要加同样的锁,不能遗漏。
  • 如果InGameState_t的成员变量也会被多线程访问,那这些成员也需要单独的同步保护(比如给Message加锁,或者用原子变量)。
  • 避免在持有锁的时候执行耗时操作(比如网络IO),否则会阻塞其他线程,降低并发性能。

四、验证思路

先加同步锁测试,如果指针失效问题消失,就确认是多线程竞争导致的。如果还有问题,再检查InGameState_t的构造函数是否正确初始化成员,或者Message的拷贝逻辑是否有内存越界的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:23:59