#emit & return - Invalid memory access
#1

Hello everyone,
I am requesting help with a function to format a local string with x arguments, the string have already the %s %d characters. Here is it:
Code:
getMessageA(const playerid, const key[], { Float, _ }: ...)
{
	new value[144];
//Some stuff
	GetGVarString(key2, value);//Value is the string I want to format, it's a local variable as you can see. I had it as an static variable but it was causing the same error that the return causes now (Invalid memory access)
	new args = (numargs() - 3) << 2;
    if(args)
	{
		static s_szBuf[144], s_iAddr1, s_iAddr2;//Using s_szBuf as "new" crashes the server
        #emit ADDR.PRI value
        #emit STOR.PRI s_iAddr1
        for(s_iAddr2 = s_iAddr1 + args, args += 12; s_iAddr2 != s_iAddr1; s_iAddr2 -= 4)
        {
            #emit LOAD.PRI s_iAddr2
            #emit LOAD.I
            #emit PUSH.PRI
        }
        #emit CONST.PRI s_szBuf
        #emit PUSH.S value
        #emit PUSH.C 144
        #emit PUSH.PRI
        #emit PUSH.S args
        #emit SYSREQ.C format
        #emit LCTRL 4
        #emit LOAD.S.ALT args
        #emit ADD.C 4
        #emit ADD
        #emit SCTRL 4
		return s_szBuf;//This is line 165
	}
	return value;
}
I get:
[18:19:39] [debug] Run time error 5: "Invalid memory access"
[18:19:39] [debug] AMX backtrace:
[18:19:39] [debug] #0 00009f78 in getMessageA(playerid=0, key[]=@0001ef50 "SURHAVE", ... <2 arguments>) at C:blah\pawno\include\language.inc:165
[18:19:39] [debug] #1 0000a5a4 in main () at GM.pwn:196
[18:19:39] Script[gamemodes/GM.amx]: Run time error 5: "Invalid memory access"

I have a sendMessage function like this and it is working fine:
Code:
stock sendMessage(const iPlayer, const iColor, const szFormat[], { Float, _ }: ...)
{
    new iArgs = (numargs() - 3) << 2;
    if(iArgs)
    {
        static s_szBuf[144], s_iAddr1, s_iAddr2;
        #emit ADDR.PRI szFormat
        #emit STOR.PRI s_iAddr1
        for(s_iAddr2 = s_iAddr1 + iArgs, iArgs += 12; s_iAddr2 != s_iAddr1; s_iAddr2 -= 4)
        {
            #emit LOAD.PRI s_iAddr2
            #emit LOAD.I
            #emit PUSH.PRI
        }
        #emit CONST.PRI s_szBuf
        #emit PUSH.S szFormat
        #emit PUSH.C 144
        #emit PUSH.PRI
        #emit PUSH.S iArgs
        #emit SYSREQ.C format
        #emit LCTRL 4
        #emit LOAD.S.ALT iArgs
        #emit ADD.C 4
        #emit ADD
        #emit SCTRL 4
        return (iPlayer != -1) ? SendClientMessage(iPlayer, iColor, s_szBuf) : SendClientMessageToAll(iColor, s_szBuf);
    }
    return (iPlayer != -1) ? SendClientMessage(iPlayer, iColor, szFormat) : SendClientMessageToAll(iColor, szFormat);
}
I don't get it I am not familiar with #emit
Reply
#2

In getMessageA:
pawn Code:
//Change this:
new args = (numargs() - 3) << 2;
//To this:
new args = (numargs() - 2) << 2;
Why? Well, your sendMessage has 3 parameters before the variable arguments, while getMessageA has only 2.
Reply
#3

Thank you Misiur, it should fix a lot of things, unfortunately the error is still there, I think it is related with the AMX memory? but I can't figure what I must edit
Reply
#4

Yup, I can see few more problems, such as loading "ADDR.PRI value" - you want "ADDR.PRI key" there. I have to sleep now, but if nobody helps you before I get up I'll try to fiddle around some more.
Reply
#5

pawn Code:
stock getMessageA(const key[], { Float, _ }: ...)
{
    static value[144];
    GetGVarString(key, value);

    new args = (numargs() - 1) << 2;

    if(args)
    {
        static s_szBuf[144], s_iAddr1, s_iAddr2;
        #emit ADDR.PRI key
        #emit STOR.PRI s_iAddr1

        for(s_iAddr2 = s_iAddr1 + args, args += 12; s_iAddr2 != s_iAddr1; s_iAddr2 -= 4)
        {
            #emit LOAD.PRI s_iAddr2
            #emit LOAD.I
            #emit PUSH.PRI
        }
        #emit CONST.PRI s_szBuf
        #emit PUSH.C value
        #emit PUSH.C 144
        #emit PUSH.PRI
        #emit PUSH.S args
        #emit SYSREQ.C format
        #emit LCTRL 4
        #emit LOAD.S.ALT args
        #emit ADD.C 4
        #emit ADD
        #emit SCTRL 4

        return s_szBuf;//This is line 165
    }
    return value;
}
For some reason I had to change value to static, because when I did normal PUSH.S the string got mangled somehow, but with PUSH.C works. Weird. Anyway: if you're using YSI, there's y_va library, which is as easy as
pawn Code:
YouFunction(const key[], va_args<>) {
    new value[144], result[144];
    GetGVarString(key, value);
    va_format(result, sizeof result, value, va_start<1>);
    return result;
}
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)