mercredi 29 juin 2016

Why does this function cause a crash if accessed via a pointer?

I have the following code:

void Aurora64::Messaging::SendConsoleMessageToPlayer(int channelId , const char *msg) 
{
    CGameRules *pGameRules = new CGameRules;
    pGameRules->SendTextMessage(eTextMessageConsole, msg, eRMI_ToClientChannel, channelId);
    delete(pGameRules);
}

It accesses a function in another class through pointer pGameRules, however the function causes the program to crash when it is called.

This code is inside the Aurora64 class in another file.


When placing the following code inside the pointer's class CGameRules (in a function that is executed inside it), the program crashes:

CGameRules *pGameRules = new CGameRules;
pGameRules->SendTextMessage(eTextMessageConsole, "$4test", eRMI_ToClientChannel, channelId);
delete(pGameRules);

This was experimenting whether something in the Aurora64 class file was causing the crash (it wasn't).

However when placed inside the same class, the program works perfectly with no crashes:

SendTextMessage(eTextMessageConsole, "$4test", eRMI_ToClientChannel, channelId);

Other than the pointer, the code is functionally identical (using the same input values).


The call stack is:

Aurora64.dll!IGameObject::GetEntityId() Line 301    C+Aurora64.dll!IGameObject::InvokeRMI_Primitive<CGameRules::MethodInfo_ClTextMessage,
          CGameRules::TextMessageParams>(const CGameRules::MethodInfo_ClTextMessage method, 
          const CGameRules::TextMessageParams
            & params, unsigned int where,
          IRMIListener * pListener, int userId, int channel, unsigned int dependentId)
          Line 281  C++
Aurora64.dll!IGameObject::InvokeRMI<CGameRules::MethodInfo_ClTextMessage,
          CGameRules::TextMessageParams>(const
          CGameRules::MethodInfo_ClTextMessage method, const CGameRules::TextMessageParams 
          & params, unsigned int where, int channel) 
          Line 275  C++
Aurora64.dll!CGameRules::SendTextMessage(ETextMessageType type, const char * msg, unsigned int
          to, int channelId, const char * p0, const char * p1, const char * p2, 
          const char * p3)
          Line 3075 C++
Aurora64.dll!CGameRules::OnClientConnect(int channelId, bool isReset) Line 596  C++


I don't understand why it's crashing... the code should technically work since the exact same function is being called, with the exact same input.

I have the source-code on GitHub should it be required (it does not have the Aurora64 class as it's another project based on the one from GitHub, but the source hasn't been changed). It's also likely that to debug it the Crysis Wars game and dedicated server package would be required, making it harder for anyone here to debug.

The problem with this might be something really obvious that I'm missing.

What am I doing wrong?


The SendTextMessage method:

int CScriptBind_GameRules::SendTextMessage(IFunctionHandler *pH, int type, const char *msg)
{
    CGameRules *pGameRules=GetGameRules(pH);

    if (!pGameRules)
        return pH->EndFunction();

    int to=eRMI_ToAllClients;
    int channelId=-1;

    if (pH->GetParamCount()>2)
        pH->GetParam(3, to);

    if (pH->GetParamCount()>3)
    {
        if (pH->GetParamType(4)==svtPointer)
        {
            ScriptHandle playerId;
            pH->GetParam(4, playerId);

            channelId=pGameRules->GetChannelId((EntityId)playerId.n);
        }
        else if (pH->GetParamType(4)==svtNumber)
            pH->GetParam(4, channelId);
    }

    if (pH->GetParamCount()>4)
    {
        string p[4];
        for (int i=0;i<pH->GetParamCount()-4;i++)
        {
            switch(pH->GetParamType(5+i))
            {
            case svtPointer:
                {
                    ScriptHandle sh;
                    pH->GetParam(5+i, sh);

                    if (IEntity *pEntity=gEnv->pEntitySystem->GetEntity((EntityId)sh.n))
                        p[i]=pEntity->GetName();
                }
                break;
            default:
                {
                    ScriptAnyValue value;
                    pH->GetParamAny(5+i, value);
                    switch(value.GetVarType())
                    {
                    case svtNumber:
                        p[i].Format("%g", value.number);
                        break;
                    case svtString:
                        p[i]=value.str;
                        break;
                    case svtBool:
                        p[i]=value.b?"true":"false";
                        break;
                    default:
                        break;
                    }           
                }
                break;
            }
        }
        pGameRules->SendTextMessage((ETextMessageType)type, msg, to, channelId, 
            p[0].empty()?0:p[0].c_str(),
            p[1].empty()?0:p[1].c_str(),
            p[2].empty()?0:p[2].c_str(),
            p[3].empty()?0:p[3].c_str()
            );
    }
    else
        pGameRules->SendTextMessage((ETextMessageType)type, msg, to, channelId);

    return pH->EndFunction();
}

Aucun commentaire:

Enregistrer un commentaire