From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by c5ff346549e7 (Postfix) with ESMTPS id 1120B5D5 for ; Sun, 6 May 2018 19:23:52 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.49,371,1520895600"; d="scan'208,217";a="325967402" Received: from sympa.inria.fr ([193.51.193.213]) by mail2-relais-roc.national.inria.fr with ESMTP; 06 May 2018 21:23:51 +0200 Received: by sympa.inria.fr (Postfix, from userid 20132) id CAF6482416; Sun, 6 May 2018 21:23:51 +0200 (CEST) Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id 31E838240C for ; Sun, 6 May 2018 21:23:45 +0200 (CEST) Authentication-Results: mail2-smtp-roc.national.inria.fr; spf=None smtp.pra=murthy.chet@gmail.com; spf=Pass smtp.mailfrom=murthy.chet@gmail.com; spf=None smtp.helo=postmaster@mail-ua0-f170.google.com IronPort-PHdr: =?us-ascii?q?9a23=3ApLLPHB+rG+Y8HP9uRHKM819IXTAuvvDOBiVQ1KB2?= =?us-ascii?q?0u4cTK2v8tzYMVDF4r011RmVBd6ds6oMotGVmpioYXYH75eFvSJKW713fDhBt/?= =?us-ascii?q?8rmRc9CtWOE0zxIa2iRSU7GMNfSA0tpCnjYgBaF8nkelLdvGC54yIMFRXjLwp1?= =?us-ascii?q?Ifn+FpLPg8it2O2+55Pebx9UiDahfLh/MAi4oQLNu8cMnIBsMLwxyhzHontJf+?= =?us-ascii?q?RZ22ZlLk+Nkhj/+8m94odt/zxftPw9+cFAV776f7kjQrxDEDsmKWE169b1uhTF?= =?us-ascii?q?UACC+2ETUmQSkhpPHgjF8BT3VYr/vyfmquZw3jSRMNboRr4oRzut86ZrSAfpiC?= =?us-ascii?q?gZMT457HrXgdF0gK5CvR6tuwBzz4vSbY6SKfR+Y7jdfcsESmVdQsZfWStBAoam?= =?us-ascii?q?YIsOCeoKIOJUoob5qlcLqxa1GAuiC/71yjJQhHD206003eoiHw/bwgIvA8kDv2?= =?us-ascii?q?7IoNjvLqoeTfy5wavOwD7eb/1WwzD96I3Qfx0/ofGDQ65wetfWx0kyDQPFklWQ?= =?us-ascii?q?qIz4ND6S0+QNrnKb7/ZgVeOvkWIotwFxrSazxso3hYnJg5gaylHA9Slj3Ik1It?= =?us-ascii?q?i4RVd9bNW5HpVQsCSaOJF3QsMkW2xouSA6yqcHuZGhZiQKxo4nywbfavOdc4iI?= =?us-ascii?q?5RXjWPyNLjd/gXJofq+0iRWq8UW41OHwSs253ExJoydFiNXAqG0B2h7J5sSaSP?= =?us-ascii?q?Zx4kGs0iuV2Q/J8OFLO0U0mLLbK5E/xr4wkYIesUHZES/3nEX6lbKWeV849uSx?= =?us-ascii?q?5eTrf7frqoOGO497jQH+NasumsihDugiLgcOWG2b9fy91L3l40L5XK1HguMqnq?= =?us-ascii?q?TdqpzXJsQWqrSnDwNI0Isv8QuzAjW63NgAmHkINlNFeBaJj4jzPFHOJej1DfKi?= =?us-ascii?q?g1S2jDdrx/DHMqf9DZXNMHfDjKzsfbl460FGyQozycpT6I5TCrEEOP7zQFP+tM?= =?us-ascii?q?TEDh8lNAy52+nmCNFj2YMEXmKOArSUMaLTsV+N/e0vOfODaJUUuDb7Mfgl5uTh?= =?us-ascii?q?gWU3mV8HZaOpx4cYaGikHvR6JEWUeWbjjc0EEWcOpwY+SO3qiEaeUTNIfHazX6?= =?us-ascii?q?c85ikhB468DIfDQJqtgL2b0yuhEJ1WfDMONlfZIX72doieE9MBciWDaptRmyIF?= =?us-ascii?q?WKLnb4I70gCGtQngyrMhIPCCqQMCspe2/9h4+6X2iAsu9S08W8GAyX2NXid/nm?= =?us-ascii?q?4UbzAz1aF750d6zwHQguBDn/VEGIkLtLtyWQAgOMuZkrUjWoLCHznZd9LMc26I?= =?us-ascii?q?B9CvADU/VNU0moZcbEN0GtHkhRfGjXPzX+0l0oeTDZlxyZrymmDrLp8kmXnD3a?= =?us-ascii?q?glyVIhR5kXbDD0tutE7wHWQrXxvQCZmqKtL/pO2SfM8CKexDLLshgHCEh/VqLK?= =?us-ascii?q?WX1ZbUzT/4z0?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0DiAQCMVe9ahqrZVdFcGQEBAQEBAQEBA?= =?us-ascii?q?QEBAQcBAQEBAYQlF2MoCoMlP4EdglCRB4F5AoENgUCTXgsjhEkCgjEHGQcBBDM?= =?us-ascii?q?VAQIBAQEBAQEBAQETAQEBCAsLCCgjDII1JIJPAQEBAQIBDBIFHQEbEgsBAwwGA?= =?us-ascii?q?wILDQ0dAgIhAQERAQUBChIGExIJhG0BAw0ID4tCkAA8iwWBfwUBF4JwBYNGChk?= =?us-ascii?q?mAwpUV4IwAgYSiBOCE4MbSjWCTzeCGoJTglQChhAIhl+LBywIhWWFa4J9XVg8h?= =?us-ascii?q?gOEbodBggVJhi4PAx6BBAwmgXQzGiNQMYISCYFnJAwOCYNFgT6JNB8wjWIqghw?= =?us-ascii?q?BAQ?= X-IPAS-Result: =?us-ascii?q?A0DiAQCMVe9ahqrZVdFcGQEBAQEBAQEBAQEBAQcBAQEBAYQ?= =?us-ascii?q?lF2MoCoMlP4EdglCRB4F5AoENgUCTXgsjhEkCgjEHGQcBBDMVAQIBAQEBAQEBA?= =?us-ascii?q?QETAQEBCAsLCCgjDII1JIJPAQEBAQIBDBIFHQEbEgsBAwwGAwILDQ0dAgIhAQE?= =?us-ascii?q?RAQUBChIGExIJhG0BAw0ID4tCkAA8iwWBfwUBF4JwBYNGChkmAwpUV4IwAgYSi?= =?us-ascii?q?BOCE4MbSjWCTzeCGoJTglQChhAIhl+LBywIhWWFa4J9XVg8hgOEbodBggVJhi4?= =?us-ascii?q?PAx6BBAwmgXQzGiNQMYISCYFnJAwOCYNFgT6JNB8wjWIqghwBAQ?= X-IronPort-AV: E=Sophos;i="5.49,371,1520895600"; d="scan'208,217";a="325967397" Received: from mail-ua0-f170.google.com ([209.85.217.170]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/AES128-GCM-SHA256; 06 May 2018 21:23:43 +0200 Received: by mail-ua0-f170.google.com with SMTP id e8so14846869uam.13; Sun, 06 May 2018 12:23:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=/EsF1QmQH7Iq5YFEYK35enbrTeoSCAm1/1oWKSFCuKA=; b=KKYSjTK8eEYlr5dDuHnWaIDpmDomgvN53jZWnMwxxyCYU5IHOeU+KIfv4RrrdwlcYL Qewnv1ONujC6EMNJSZHr7HjAxjPJTUGEOKHk0SUqs21Oa8utmHWjsiHakZAp9R7jNbSS i7eYUAfCCsfrvtJeqc6JaeU2pf8iFVP6vtQ1DPcauSlZ0MU3h7F8Lz+mW152zMzVADsB 3C0a+bjnIS3zH2Nl86xlB+xJqT15M+yFiTXY03P9GDzUrp7+mOOJKQGlu0nEYVp8cIGz 9DqgeYZpQzAKhVAROO7lMwuHwPKU2pscp88g/8L5vaY2BI+Zcp0B26gq9IQzNSI/e/Qy yVmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=/EsF1QmQH7Iq5YFEYK35enbrTeoSCAm1/1oWKSFCuKA=; b=GyjQHEk55iLkh1YbaxKueJCFNz5P6/kycN6F5y+0cWfxSqKJgCwGwRhvr0J1ihZrqK QrvauVkqalCnLMBavrms69X5DGeRt3rslkiVaVvDI+ptoSUdrugHV12n0el5ITC31wqH qO0AtnJ9FARyIP4uuyfFsAIHvXz/hN5ZFUN/WxIfIkqU7PdPOoLpqVAWOV6UFGEYVFJF VbEml3enKwklPWE44lsBIw+4jHpm5La6AQryuzFhekKE6Z7FrYkbooTEquihSwAAVlAR FEEjJHJHgteBuvytQM/PdVQHAI3mBrj7Lirnt/uCvF4Wii7GYZvuQXhA6Sr1tIdTOaLR gf2A== X-Gm-Message-State: ALQs6tAOZB141S99CKdkga2opa4eurCufumrzW42WslSxyG/gjdfhg9L 8leCgaYB+ahE21y9ivujIxIlZD5qzzYxxIrb1hw= X-Google-Smtp-Source: AB8JxZpa1c6nZLjd4MhATPHlHffo0AngUUJbGYlnW0sK/T/uddm9a1/T/34Yq1ZGya86dF6S/Ln016udEIIJKW/Q2V0= X-Received: by 10.159.40.35 with SMTP id c32mr31694106uac.193.1525634622139; Sun, 06 May 2018 12:23:42 -0700 (PDT) MIME-Version: 1.0 Received: by 10.176.97.134 with HTTP; Sun, 6 May 2018 12:23:41 -0700 (PDT) In-Reply-To: References: From: Chet Murthy Date: Sun, 6 May 2018 12:23:41 -0700 Message-ID: To: Xavier Leroy Cc: Frederic Perriot , caml-list Content-Type: multipart/alternative; boundary="94eb2c048be0b5b3dc056b8e7dc4" Subject: Re: [Caml-list] an implicit GC rule? Reply-To: Chet Murthy X-Loop: caml-list@inria.fr X-Sequence: 16880 Errors-to: caml-list-owner@inria.fr Precedence: list Precedence: bulk Sender: caml-list-request@inria.fr X-no-archive: yes List-Id: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --94eb2c048be0b5b3dc056b8e7dc4 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Oh shit, and also, uh, oh right! I forgot that (for example in Tree((v1 =3D e1), (v2 =3D e2)) it could transpire that after evaluating e1 and assigning to v1, the evaluation of e2 could end up moving the value pointed-to by v1, updaiting v1, but NOT updating the result of the expression (v1 =3D e1) (b/c of course, it's evaluated and on-stack waiting for the call to Tree(). Oof. On Sat, May 5, 2018 at 12:42 AM, Xavier Leroy wrote: > > > On Sat, May 5, 2018 at 5:25 AM Chet Murthy wrote: > >> It's been a while since I did this sort of thing, but I suspect if you >> declare CAMLlocal variables for each intermediate expression, and stick = in >> the assignments, that should solve your problem (while not making your c= ode >> too ugly). E.g. >> >> CAMLprim value left_comb(value a, value b, value c) >> { >> CAMLparam3(a, b, c); >> CAMLlocal5(l1, l2, l3, l4, l5); >> CAMLreturn(l1 =3D Tree(l2 =3D Tree((l3 =3D Leaf(a)), (l4 =3D Leaf(b)= ), (l5 =3D >> Leaf(c)))); >> } >> > > That's bold C/C++ programming! It might even work in C++, where > assignment expressions are l-values if I remember correctly. > > However, I'm afraid it won't work in C because an assignment expression > "lv =3D rv" is a r-value equal to the value of rv converted to the type o= f lv > at the time the assignment is evaluated. So, if lv is a local variable > registered with the GC, the GC will update lv when needed, but the "lv =3D > rv" expression will keep its initial value. > > There's also the rules concerning sequence points. I think the code above > respects the C99 rules but I'm less sure about the C11 rules. > >> >> Even better, you could linearize the tree of expressions into a sequence, >> and that should solve your problem, also. >> > > Yes, that's the robust solution. Spelling it out: > > CAMLprim value left_comb(value a, value b, value c) > { > CAMLparam3(a, b, c); > CAMLlocal5(la, lb, lc, tab, t); > la =3D Leaf(a); > lb =3D Leaf(b); > lc =3D Leaf(c); > tab =3D Tree(la, lb); > t =3D Tree(tab, lc); > CAMLreturn(t); > } > > You can also do "CAMLreturn(Tree(tab, lc))" directly. > > - Xavier Leroy > > >> Uh, I think. Been a while since I wrote a lotta C/C++ code to interface >> with Ocaml, but this oughta work. >> >> --chet-- >> >> >> On Wed, May 2, 2018 at 9:09 AM, Frederic Perriot >> wrote: >> >>> Hello caml-list, >>> >>> I have a GC-related question. To give you some context, I'm writing a >>> tool to parse .cmi files and generate .h and .c files, to facilitate >>> constructing OCaml variants from C bindings. >>> >>> For instance, given the following source: >>> >>> type 'a tree =3D Leaf of 'a | Tree of 'a tree * 'a tree [@@h_file] >>> >>> >>> the tool produces C functions: >>> >>> CAMLprim value Leaf(value arg1) >>> { >>> CAMLparam1(arg1); >>> CAMLlocal1(obj); >>> >>> obj =3D caml_alloc_small(1, 0); >>> >>> Field(obj, 0) =3D arg1; >>> >>> CAMLreturn(obj); >>> } >>> >>> CAMLprim value Tree(value arg1, value arg2) >>> { >>> // similar code here >>> } >>> >>> >>> From there, it's tempting to nest calls to variant constructors from C >>> and write code such as: >>> >>> CAMLprim value left_comb(value a, value b, value c) >>> { >>> CAMLparam3(a, b, c); >>> CAMLreturn(Tree(Tree(Leaf(a), Leaf(b)), Leaf(c))); >>> } >>> >>> >>> The problem with the above is the GC root loss due to the nesting of >>> calls to allocating functions. >>> >>> Say Leaf(c) is constructed first, and the resulting value cached in a >>> register, then Leaf(b) triggers a collection, thus invalidating the >>> register contents, and leaving a dangling pointer in the top Tree. >>> >>> Here is an actual ocamlopt output, with Leaf(c) getting cached in rbx: >>> >>> 0x000000000040dbf4 <+149>: callq 0x40d8fd >>> 0x000000000040dbf9 <+154>: mov %rax,%rbx >>> 0x000000000040dbfc <+157>: mov -0x90(%rbp),%rax >>> 0x000000000040dc03 <+164>: mov %rax,%rdi >>> 0x000000000040dc06 <+167>: callq 0x40d8fd >>> 0x000000000040dc0b <+172>: mov %rax,%r12 >>> 0x000000000040dc0e <+175>: mov -0x88(%rbp),%rax >>> 0x000000000040dc15 <+182>: mov %rax,%rdi >>> 0x000000000040dc18 <+185>: callq 0x40d8fd >>> 0x000000000040dc1d <+190>: mov %r12,%rsi >>> 0x000000000040dc20 <+193>: mov %rax,%rdi >>> 0x000000000040dc23 <+196>: callq 0x40da19 >>> 0x000000000040dc28 <+201>: mov %rbx,%rsi >>> 0x000000000040dc2b <+204>: mov %rax,%rdi >>> 0x000000000040dc2e <+207>: callq 0x40da19 >>> >>> >>> While the C code clearly violates the spirit of the GC rules, I can't >>> help but feel this is still a pitfall. >>> >>> Rule 2 of the manual states: "Local variables of type value must be >>> declared with one of the CAMLlocal macros. [...]" >>> >>> But here, I'm not declaring local variables, unless you count compiler >>> temporaries as local variables? >>> >>> I can see some other people making the same mistake I did. Should >>> there be an explicit warning in the rules? maybe underlining that >>> compiler temps count as variables, or discouraging the kind of nested >>> calls returning values displayed above? >>> >>> thanks, >>> Fr=C3=A9d=C3=A9ric Perriot >>> >>> PS: this is also my first time posting to the list, so I take this >>> opportunity to thank you for the great Q's and A's I've read here over >>> the years >>> >>> -- >>> Caml-list mailing list. Subscription management and archives: >>> https://sympa.inria.fr/sympa/arc/caml-list >>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >>> Bug reports: http://caml.inria.fr/bin/caml-bugs >> >> >> --=20 Caml-list mailing list. Subscription management and archives: https://sympa.inria.fr/sympa/arc/caml-list Beginner's list: http://groups.yahoo.com/group/ocaml_beginners Bug reports: http://caml.inria.fr/bin/caml-bugs= --94eb2c048be0b5b3dc056b8e7dc4 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Oh shit, and also, uh, oh right!=C2=A0 I forgot that (for = example in Tree((v1 =3D e1), (v2 =3D e2)) it could transpire that after eva= luating e1 and assigning to v1, the evaluation of e2 could end up moving th= e value pointed-to by v1, updaiting v1, but NOT updating the result of the = expression (v1 =3D e1) (b/c of course, it's evaluated and on-stack wait= ing for the call to Tree().

Oof.

On Sat, May 5, 2018 at 12:4= 2 AM, Xavier Leroy <Xavier.Leroy@inria.fr> wrote:


On Sat, May 5, 2018 at 5:25 AM Chet = Murthy <murth= y.chet@gmail.com> wrote:
It's been a while since I did this sort of thing, bu= t I suspect if you declare CAMLlocal variables for each intermediate expres= sion, and stick in the assignments, that should solve your problem (while n= ot making your code too ugly).=C2=A0 E.g.

CAMLprim value left_comb(value a, value b, v= alue c)
{
=C2=A0 =C2=A0 CAMLparam3(a, b, c);
=C2=A0 CAMLlocal5(l1, l2, l3,=C2=A0 l4, l= 5);
=C2=A0 =C2=A0 CAMLreturn(l1 =3D Tree(l2 =3D Tree((l3 =3D Leaf= (a)), (l4 =3D Leaf(b)), (l5 =3D Leaf(c))));
}

That's bold C/C++ programming!=C2= =A0 It might even work in C++, where assignment expressions are l-values if= I remember correctly. =C2=A0

However, I'm afraid it won't = work in C because an assignment expression "lv =3D rv" is a r-val= ue equal to the value of rv converted to the type of lv at the time the ass= ignment is evaluated.=C2=A0 So, if lv is a local variable registered with t= he GC, the GC will update lv when needed, but the "lv =3D rv" exp= ression will keep its initial value.

There's also the= rules concerning sequence points.=C2=A0 I think the code above respects th= e C99 rules but I'm less sure about the C11 rules.

E= ven better, you could linearize the tree of expressions into a sequence, an= d that should solve your problem, also.

Yes, that's the robust solution.=C2=A0 Spelling it out:=

CAMLprim value left_com= b(value a, value b, value c)
{
=C2=A0 CAMLparam3(a, b, c);
=C2=A0 CAMLlocal5(la, lb, l= c, tab, t);
=C2=A0 la =3D Leaf(a);
=C2=A0 lb = =3D Leaf(b);
=C2=A0 lc =3D Leaf(c);
=C2=A0 tab = =3D Tree(la, lb);
=C2=A0 t =3D Tree(tab, lc);
= =C2=A0 CAMLreturn(t);
}

You can also do = "CAMLreturn(Tree(tab, lc))" directly.

- Xavier Leroy


Uh, I think.=C2=A0 Been a while since I wrote a lotta C/C++ code to = interface with Ocaml, but this oughta work.

--chet--


On Wed, May 2, 2018 at 9:09 AM, Frederic= Perriot <fperriot@gmail.com> wrote:
Hello caml-list,

I have a GC-related question. To give you some context, I'm writing a tool to parse .cmi files and generate .h and .c files, to facilitate
constructing OCaml variants from C bindings.

For instance, given the following source:

type 'a tree =3D Leaf of 'a | Tree of 'a tree * 'a tree [@@= h_file]


the tool produces C functions:

CAMLprim value Leaf(value arg1)
{
=C2=A0 =C2=A0 CAMLparam1(arg1);
=C2=A0 =C2=A0 CAMLlocal1(obj);

=C2=A0 =C2=A0 obj =3D caml_alloc_small(1, 0);

=C2=A0 =C2=A0 Field(obj, 0) =3D arg1;

=C2=A0 =C2=A0 CAMLreturn(obj);
}

CAMLprim value Tree(value arg1, value arg2)
{
=C2=A0 // similar code here
}


>From there, it's tempting to nest calls to variant constructors from C<= br> and write code such as:

CAMLprim value left_comb(value a, value b, value c)
{
=C2=A0 =C2=A0 CAMLparam3(a, b, c);
=C2=A0 =C2=A0 CAMLreturn(Tree(Tree(Leaf(a), Leaf(b)), Leaf(c)));
}


The problem with the above is the GC root loss due to the nesting of
calls to allocating functions.

Say Leaf(c) is constructed first, and the resulting value cached in a
register, then Leaf(b) triggers a collection, thus invalidating the
register contents, and leaving a dangling pointer in the top Tree.

Here is an actual ocamlopt output, with Leaf(c) getting cached in rbx:

=C2=A0 =C2=A00x000000000040dbf4 <+149>:=C2=A0 =C2=A0 callq=C2=A0 0x40= d8fd <Leaf>
=C2=A0 =C2=A00x000000000040dbf9 <+154>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= %rax,%rbx
=C2=A0 =C2=A00x000000000040dbfc <+157>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= -0x90(%rbp),%rax
=C2=A0 =C2=A00x000000000040dc03 <+164>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= %rax,%rdi
=C2=A0 =C2=A00x000000000040dc06 <+167>:=C2=A0 =C2=A0 callq=C2=A0 0x40= d8fd <Leaf>
=C2=A0 =C2=A00x000000000040dc0b <+172>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= %rax,%r12
=C2=A0 =C2=A00x000000000040dc0e <+175>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= -0x88(%rbp),%rax
=C2=A0 =C2=A00x000000000040dc15 <+182>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= %rax,%rdi
=C2=A0 =C2=A00x000000000040dc18 <+185>:=C2=A0 =C2=A0 callq=C2=A0 0x40= d8fd <Leaf>
=C2=A0 =C2=A00x000000000040dc1d <+190>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= %r12,%rsi
=C2=A0 =C2=A00x000000000040dc20 <+193>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= %rax,%rdi
=C2=A0 =C2=A00x000000000040dc23 <+196>:=C2=A0 =C2=A0 callq=C2=A0 0x40= da19 <Tree>
=C2=A0 =C2=A00x000000000040dc28 <+201>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= %rbx,%rsi
=C2=A0 =C2=A00x000000000040dc2b <+204>:=C2=A0 =C2=A0 mov=C2=A0 =C2=A0= %rax,%rdi
=C2=A0 =C2=A00x000000000040dc2e <+207>:=C2=A0 =C2=A0 callq=C2=A0 0x40= da19 <Tree>


While the C code clearly violates the spirit of the GC rules, I can't help but feel this is still a pitfall.

Rule 2 of the manual states: "Local variables of type value must be
declared with one of the CAMLlocal macros. [...]"

But here, I'm not declaring local variables, unless you count compiler<= br> temporaries as local variables?

I can see some other people making the same mistake I did. Should
there be an explicit warning in the rules? maybe underlining that
compiler temps count as variables, or discouraging the kind of nested
calls returning values displayed above?

thanks,
Fr=C3=A9d=C3=A9ric Perriot

PS: this is also my first time posting to the list, so I take this
opportunity to thank you for the great Q's and A's I've read he= re over
the years

--
Caml-list mailing list.=C2=A0 Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


--94eb2c048be0b5b3dc056b8e7dc4--