From gb at tal.stat.umu.se  Fri Dec 31 11:33:25 2004
From: gb at tal.stat.umu.se (=?iso-8859-1?Q?G=F6ran_Brostr=F6m?=)
Date: Fri Dec 31 11:33:29 2004
Subject: [Rd] optim/vmmin and R_alloc
In-Reply-To: <Pine.A41.4.61b.0412301418350.219480@homer09.u.washington.edu>
References: <20041230155513.GA22178@tal.stat.umu.se>
	<Pine.A41.4.61b.0412300757350.11816@homer11.u.washington.edu>
	<20041230185913.GA1735@tal.stat.umu.se>
	<Pine.A41.4.61b.0412301418350.219480@homer09.u.washington.edu>
Message-ID: <20041231103325.GA5410@tal.stat.umu.se>

On Thu, Dec 30, 2004 at 02:28:49PM -0800, Thomas Lumley wrote:
> On Thu, 30 Dec 2004, [iso-8859-1] G?ran Brostr?m wrote:
> 
> >On Thu, Dec 30, 2004 at 08:01:41AM -0800, Thomas Lumley wrote:
> >>On Thu, 30 Dec 2004, [iso-8859-1] G?ran Brostr?m wrote:
> >>>
> >>>However, and that is my question/suggestion: Why not use Calloc+Free
> >>>instead of R_alloc in vmmin (and maybe in other places)? I made the
> >>>changes in 'optim.c' in the functions 'vmmin' and 'Lmatrix'. Then I 
> >>>rebuilt
> >>>and reinstalled R-2.0.1. The result was great! My function ran very fast
> >>>and
> >>>without any memory problems.
> >>>
> >>>So why not? Or will this change create other problems?
> >>
> >>Memory will leak permanently if the functions are interrupted or an error
> >>occurs.
> >
> >Not necessarily. If you take a closer look at TFM (as I just did), you find
> >in Section 5.1.2:
> >
> >Users should arrange to  Free  this memory when no longer needed, including
> >on error or user interrupt. This can often be done most conveniently from
> >an  on.exit  action in the calling  R  function -- see pwilcox for an
> >example.
> 
> Yes, this could be done.  It would require a second C call (vmfree, say) 
> that freed the memory, and would require all uses of vmmin to have an 
> on.exit() action that called this vmfree.

Thanks again, now we're getting somewhere. It is time for me to summarize
the discussion on memory handling in C code. The recommendations seem to be

1. If your code will be called exclusively from R, use R_alloc, together
   with vmaxget and vmaxset if necessary. In this way memory will be freed
   by R on exit from .C and also if your code breaks by user interrupt or
   error. 

2. If you want your code to be of use also in standalone C programs, use
   Calloc and Free. But then you have to take care of error and interrupt
   handling in R yourself. When using Calloc+Free, you need to be careful;
   each call to Calloc must be matched by exactly one call to Free.

Regarding 1., "Writing R Extensions" needs to  be changed in Section
5.1.1. The sentence "This is only recommended for experts" should be
replaced by something like: "This can for example be done as follows in
your C function:

    char *vmax;
    .....
    vmax = vmaxget();
    vmmin(.................);
    vmaxset(vmax);
    .... 

This will free all the memory that vmmin allocated and didn't free."
(A comment: vmmin could benefit from using vmax[gs]et internally.)

Regarding 2., I tried the combination vmaxget + Calloc + vmaxset, ie, I
began my function with vmax = vmaxget() and ended it with
vmaxset(vmax). The point with this is that you can free all allocated
memory with one call instead of repeated calls to Free. This seemed to work
well; however, it is undocumented, and may well be completely wrong. Other
experts will tell you.    

> Using R_alloc means that nearly 
> everyone doesn't have to worry about this, and a few unfortunate people 
> have to become experts.

I tend to disagree; using vmaxget and vmaxset doesn't require an expert. 
Or is the full story about vmax[gs]et yet to be told?

Thanks to Dr Brian, Thomas, and Mr Ripley (private communication) for
valuable input in this matter. And Happy New Year to all of you!

G?ran
-- 
 G?ran Brostr?m                    tel: +46 90 786 5223
 Department of Statistics          fax: +46 90 786 6614
 Ume? University                   http://www.stat.umu.se/egna/gb/
 SE-90187 Ume?, Sweden             e-mail: gb@stat.umu.se


[Rd] optim/vmmin and R_alloc
=?iso-8859-1?Q?G=F6ran_Brostr=F6m?=