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

为何Indy框架OnExecute事件中AContext->Data为NULL?

Indy OnExecute事件中AContext->Data为空导致Buffer空指针异常的解决思路

背景与问题

我在实现StackOverflow问题《How to display messages in every Indy event?》中的方案2——放弃阻塞式同步,改用异步同步(TIdNotify、TThread::Queue()或等效方法),避免服务器线程等待主线程更新UI。已将自定义类改为继承自TIdNotify,把原Synchronize方法替换为Notify,移除了TIdSync对象的delete语句(TIdNotify会自动释放)。

当前在OnExecute事件中使用如下代码:

String sTemp;

TIdBuffer *Buffer = static_cast<TIdBuffer*>(AContext->Data);
Buffer->Write(static_cast<TIdMappedPortContext*>(AContext)->NetData);
Buffer->CompactHead();

TTextToDisplay *TextToDisplay = new TTextToDisplay;
CDecoder *Decoder = new CDecoder();
TStringList *slDecodedLines = NULL;
TIdBytes ucBuffer;
int offset = 0;
while (ReadMessageData(Buffer, offset, ucBuffer)) {
    sTemp = String().sprintf(_D("%s"), ToHex(ucBuffer).c_str());
    slDecodedLines = Decoder->formatInput(sTemp);
    if(slDecodedLines)
    {
        TextToDisplay->AddStringList(slDecodedLines);
        TextToDisplay->Notify();
    }
}

// delete TextToDisplay;
delete Decoder;
delete slDecodedLines;

if (offset > 0)
    Buffer->Remove(offset);

代码执行到第3行时抛出空指针异常,原因是AContext->Data为NULL,导致Buffer指针为空。已实现OnBeforeConnect、OnDisconnect、OnConnect事件(这些事件能正常输出消息),即使注释这些事件内的代码,错误依然存在。

解决思路

  • 手动初始化AContext->Data:Indy的AContext->Data不会自动初始化,必须在连接建立阶段手动创建TIdBuffer并赋值。在OnConnect事件中添加初始化代码:

    void __fastcall TForm1::IdMappedPortServer1Connect(TIdContext *AContext)
    {
        AContext->Data = new TIdBuffer();
    }
    

    同时在OnDisconnect事件中释放对象,避免内存泄漏:

    void __fastcall TForm1::IdMappedPortServer1Disconnect(TIdContext *AContext)
    {
        delete static_cast<TIdBuffer*>(AContext->Data);
        AContext->Data = NULL;
    }
    
  • 确认AContext类型转换合法性:代码中把AContext强制转换为TIdMappedPortContext,需确保当前使用的Indy组件是TIdMappedPortServer——只有该组件的上下文才属于TIdMappedPortContext类型。若误用其他服务器组件(如TIdTCPServer),该转换会引发未定义行为,甚至间接影响AContext->Data的有效性。

  • 排查自定义函数的影响:检查ReadMessageData函数的实现,确保它不会意外修改AContext->Data或Buffer的状态(比如提前释放或置空指针)。

  • 添加空指针保护:在使用Buffer前增加判空逻辑,避免直接访问空指针崩溃,同时输出调试信息定位问题:

    TIdBuffer *Buffer = static_cast<TIdBuffer*>(AContext->Data);
    if (!Buffer) {
        OutputDebugString(_D("AContext->Data is NULL in OnExecute"));
        return;
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 06:25:22