kostrykin
kostrykin

Reputation: 4302

Vala string processing corrupts memory. Why and how to avoid?

I'm not sure whether I'm misusing Vala or GLib.Regex, because I'm new to both. I've created a minimal example, which reproduces the error. From the following code, I'd expect that it prints a INPUTX b six times, prefixed with source and result alternatingly:

public class Test
{
    public static void run( string src )
    {
        var regex = new Regex( "INPUT[0-9]" );
        for( int i = 0; i < 3; ++i )
        {
            stdout.printf( @"-- source: $src\n" );
            src = regex.replace( src, -1, 0, "value" );
            stdout.printf( @"-- result: $src\n\n" );
        }
    }

    public static void main()
    {
        Test.run( "a INPUTX b" );
    }
}

I wrote this code based on the example in the docs. However, after compiling with valac Test.vala --pkg glib-2.0 and running, I get:

-- source: a INPUTX b
-- result: a INPUTX b

-- source: -- source: 
-- result: N�

-- source: -- source: 
-- result: PN�

What am I doing wrong?

Upvotes: 2

Views: 129

Answers (2)

Jens M&#252;hlenhoff
Jens M&#252;hlenhoff

Reputation: 14883

Consider this (nonsense) code:

string foo (string s)
{
    return s;
}

void run (string src)
{
    var regex = new Regex( "INPUT[0-9]" );
    for( int i = 0; i < 3; ++i )
    {
        stdout.printf( @"-- source: $src\n" );
        //src = regex.replace( src, -1, 0, "value" );
        src = foo (src);
        stdout.printf( @"-- result: $src\n\n" );
    }
}

void main ()
{
    run( "a INPUTX b" );
}

The Vala compiler (rightfully) complains:

test.vala:13.2-13.16: error: Invalid assignment from owned expression to unowned variable
        src = foo (src);
        ^^^^^^^^^^^^^^^

So there must be something different for methods from vapi files, since it allows the call to Regex.replace ().

I smell a bug somewhere (either in the compiler or the vapi), but I'm not sure.

Upvotes: 0

kostrykin
kostrykin

Reputation: 4302

After looking into the generated C code, I concluded that this rather is a Vala-related issue: Vala puts a g_free to the end of the loop's body, which frees the memory returned by g_regex_replace, and that is referenced by src. But why does Vala do that?

The reason is that (see)

arguments are, by default, unowned.

Hence, when we assign the string object returned by regex.replace to the unowned string src, that reference is (see)

not recorded in the object

and the Vala compile considers it to be safe to dispose - although it's not quiet clear, why this happens particularly at the end of the loop's body.

So the straiht-forward solution is to declare the src argument as owned.

Upvotes: 2

Related Questions