githwxi / ATS-Postiats

ATS2: Unleashing the Potentials of Types and Templates
www.ats-lang.org
Other
354 stars 54 forks source link

Segfault in compiled program #243

Closed Potpourri closed 5 years ago

Potpourri commented 5 years ago

This code compiles well, but on run it gets a Segfault:

#include "share/atspre_staload.hats"

datavtype wrapper_vt(x: vt@ype) =
  | wrap_vt of x

implement(x) gfree_val<wrapper_vt(x)>(w) =
  case+ w of
  | ~wrap_vt x => gfree_val<x>(x)

implement main0() = {
  val foo: wrapper_vt(ptr) = wrap_vt(the_null_ptr)
  val () = gfree_val<wrapper_vt(ptr)>(foo)
}

Compile cmd: patscc -o segfault -DATS_MEMALLOC_LIBC segfault.dats patscc -vats: ATS/Postiats version 0.4.0 with Copyright (c) 2011-2018 Hongwei Xi gcc -v: 8.3.0

githwxi commented 5 years ago

Yes, this is a known bug in ATS: The call to gfree_val(x) was mistaken for a tail-call.

Here is a quick "fix":

implement(x) gfree_val<wrapper_vt(x)>(w) =
  case+ w of
  | ~wrap_vt x =>
    let val () = gfree_val<x>(x) in ignoret(0) end
Potpourri commented 5 years ago

Thanks for the workaround!

sparverius commented 5 years ago

Another possible way -- use the non-recursive function keyword fn and effect tracking.

(* 
// same as above
#include "share/atspre_staload.hats"

datavtype wrapper_vt(x: vt@ype) =
  | wrap_vt of x
*)

fn {a:vt@ype} wrap_vt_free (x: wrapper_vt(a)) :<!wrt> void = 
    case+ x of ~wrap_vt x => gfree_val<a> x 

implement (x) gfree_val<wrapper_vt(x)> w = wrap_vt_free<x> w

(* 
implement main0() = {
  val foo: wrapper_vt(ptr) = wrap_vt(the_null_ptr)
  val () = gfree_val<wrapper_vt(ptr)>(foo)
}
*)
githwxi commented 5 years ago

I would like to suggest the following style:

implement(x)
gfree_val<wrapper_vt(x)>
  (w) = helper(w) where
{
  fun
  helper .<>.
  (w: wrapper_vt(x)):<!wrt> void =
  case+ w of ~wrap_vt x => gfree_val<x>(x)
}