Search code examples
ats

What is the lifetime of a struct received from a free'd linear object?


Consider:

#include "share/atspre_staload.hats"

%{^
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
%}
typedef statbuf = $extype "struct stat"
extern fun cstat: (string, &statbuf? >> statbuf) -> int = "mac#stat"
extern fun S_ISDIR: int -> bool = "mac#"
extern fun stat_mode: statbuf -> int = "mac#stat_mode"
%{
#define stat_mode(x) x.st_mode
%}

datavtype statbuf_vt = STAT of statbuf

fun stat(path: string): Option_vt(statbuf_vt) =
    let
        val buf = STAT(_)
        val STAT(hole) = buf
        val res = cstat(path, hole)
        prval _ = fold@(buf)
    in
        if res = 0 then Some_vt(buf)
        else
            let
                val ~STAT(_) = buf
            in
                None_vt()
            end
    end

implement main0() =
    let
        val path = "/etc/passwd"
        val- ~Some_vt(~STAT(buf)) = stat(path)
    in
        println!(~S_ISDIR(stat_mode(buf)))
    end

What is the lifetime of buf at the end? It doesn't seem like it needs to be freed--valgrind sees 3 allocs and 3 frees, and no problems. But isn't buf part of the memory managed by that STAT linear object?


Solution

  • Note 'buf' is a flat struct. Any value that matches the pattern ~STAT(buf) is freed; before it is freed, some content in the value is copied into 'buf', which is located on the stack. The life time of 'buf' ends when the frame for calling 'main0' unwinds. There are no leaks in the presented code.