A function that takes a variable number of arguments does not properly return an array.
#1

Here is the problem:

pawn Код:
stock concat(...)
{
    static str[256];
    new it, NumArgs = numargs();
    for (new idx, ch; it < (sizeof(str) - 1) && idx < NumArgs; idx++)
    {
        new index;
        while ( it < (sizeof(str) - 1) && ( ch = getarg( idx, index++ ) ) != 0 )
            str[it++] = ch;
    }
    str[it] = 0;
    return str;
}
Somewhere in gamemode:

pawn Код:
print(concat("Hello!"));
//output: Hello!
pawn Код:
print(concat("Hello!", " My name is ", "bartekdvd."));
//output: (null)
It seems that something is screwed up. If you pass more than one argument to that function it does not properly return an array and
it isn't the problem with code in my concat function, it can be:

pawn Код:
stock concat(...)
{
    static string[] = "abcd";
    return string;
}
And the problem still exists.


But, I've found a soultion:

pawn Код:
stock FIX_concat(...)
{
    static str[256];
    new it, NumArgs = numargs();
    for (new idx, ch; it < (sizeof(str) - 1) && idx < NumArgs; idx++)
    {
        new index;
        while ( it < (sizeof(str) - 1) && ( ch = getarg( idx, index++ ) ) != 0 )
            str[it++] = ch;
    }
    str[it] = 0;

    #emit LOAD.S.PRI 0x8
    #emit ADDR.ALT 0xC
    #emit ADD
    #emit LOAD.I
    #emit MOVE.ALT
    #emit CONST.PRI str
    #emit MOVS 0x400
    #emit STACK 0x8
    #emit RETN

    return str;
}
And now:

pawn Код:
print(FIX_concat("Hello!", " My name is ", "bartekdvd."));
//output: Hello! My name is bartekdvd.
Everything is working fine, but it isn't global solution.
You have to calculate how many bytes were pushed into stack.

Another example for str being local variable:

pawn Код:
stock FIX_S_concat(...)
{
    new str[256];
    new it, NumArgs = numargs();
    for (new idx, ch; it < (sizeof(str) - 1) && idx < NumArgs; idx++)
    {
        new index;
        while ( it < (sizeof(str) - 1) && ( ch = getarg( idx, index++ ) ) != 0 )
            str[it++] = ch;
    }
    str[it] = 0;

    #emit LOAD.S.PRI 0x8
    #emit ADDR.ALT 0xC
    #emit ADD
    #emit LOAD.I
    #emit MOVE.ALT
    #emit ADDR.PRI str
    #emit MOVS 0x400
    #emit STACK 0x408
    #emit RETN

    return str;
}
This issue is caused by compiler. It doesn't handle more than one argument in these kind of functions, so you have to do it by yourself.
Reply
#2

I've experienced this bug before. I made my own sprintf function for Pawn and when I used the function as an argument in print for example, it would give me an Invalid Instruction or Native Function Failed in the server log (crashdetect plugin).
Reply
#3

I also ran into this a while ago. Here's my solution. I think the solutions are essentially the same, though, except I leave some work to the compiler.
Reply
#4

Well done ******, you made it much easier to use.

The funny thing is that the problem still exists in the newest PAWN version.
Reported.

I was thinking about injecting a dll into PAWN compiler in order to fix most common bugs like this one.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)