From bturlach@stats.adelaide.edu.au  Wed Oct 27 12:03:36 1999
From: bturlach@stats.adelaide.edu.au (Berwin Turlach)
Date: Wed, 27 Oct 1999 20:33:36 +0930 (CST)
Subject: Rdefines.h
Message-ID: <14358.56328.738238.339073@amoeba.stats.adelaide.edu.au>

Hi all,

may I request the following two changes to Rdefines.h (R 0.65.1)?

1.) Change line 106 from
        #define Free(p)        R_chk_free( (void *)(p) )
to
        #define Free(p)        R_chk_free( (void *)(p) ) , p=NULL

2.)  Add after line 79:
#define PROBLEM	{char R_problem_buf[R_PROBLEM_BUFSIZE];sprintf(R_problem_buf,

a new line 80:
#define PROBLEM	{char R_problem_buf[R_PROBLEM_BUFSIZE];sprintf(R_problem_buf,
#define MESSAGE	{char R_problem_buf[R_PROBLEM_BUFSIZE];sprintf(R_problem_buf,

The rationale behind both changes is to become more compatible with
S.h from S-PLUS.  

Additionally, I am porting some C code that I developed under S-PLUS
to R and that code has PROBLEM...RECOVER and MESSAGE...WARNING pairs
in it.  So the absence of the MESSAE macro is a small nuisance.

The way Free(p) is currently defined simply leads to R crashing when
the C code is called a second time.  (I am running R on a linux box.)
Below I include a simple .c file that demonstrates the problem and two
sample sessions with R using that code.  Once the code was compiled
with the original Rdefines.h and the other time with the modification
proposed above.

The problem seems to be that I adopted the following style of
programming: (static) global pointers are initialised to NULL and when
free'd they are reset to NULL.  The macro Free() from S-PLUS' S.h
ensures that and the same is done by the macro of Free() that I use if
the C code is not compiled for use with S-PLUS.  If the code is
compiled for linkage with S-PLUS then I check before I allocate space
to a (static) global pointer whether it is NULL.  If not, then I
assume that the C code was called earlier but that the calculations
have been interrupted, say, by the user hitting contol-c.  In that
case, I give a warning that there may be a memory leak, free the
memory to which the pointer points and allocate the memory needed for
this call to C.  Since Free() from Rdefines.h does not reset the
pointer to NULL, the test whether the pointer is NULL fails when the C
code is called the second time and the ensuing call to free() leads to
R crashing.

I am aware that the question how to handle dynamic memory allocation
in code dynamically liked to S-PLUS (and R?) is a bit controversial.
And the programming style just described makes some obvious assumption
about the behaviour of (static) global pointers in dynamically linked
code between calls to that code.  I had no problems with this strategy
with S-PLUS on Solaris and SunOS4.1.x or R on linux (after changing
Rdefines.h).  And from what I read on the s-news are r-* mailing list,
it seems as if it would work on other platforms too.  Or is anybody
aware of a platform on which this strategy might fail?

Cheers,

        Berwin

==================== test.c =========================
=== compiled via:  R SHLIB test.c ===================
#define S_Plus

#if defined(S_Plus)
#include <S.h>
#if defined(SPLUS_VERSION) && SPLUS_VERSION >= 4000
#  include <newredef.h>
#endif
#endif

static longint *p=NULL;

void BT_demo(longint n){

#if defined(S_Plus)
  if( p != NULL ){
    PROBLEM "Possible memory corruption or memory leak.\n  We"
      "advise to restart your S+ session"  WARNING(NULL_ENTRY); 
     Free(p);
  }
#endif
  p = Calloc(n,longint);
  if (p == NULL){
    PROBLEM "Could not allocate memory" ERROR;
  }
  printf("Everything fine\n");
  Free(p);
}

=============== Compiled with original Rdefines.h ==========
R : Copyright 1999, The R Development Core Team
Version 0.65.1 Release (October 07, 1999)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type	"?license" or "?licence" for distribution details.

R is a collaborative project with many contributors.
Type	"?contributors" for a list.

Type	"demo()" for some demos, "help()" for on-line help, or
    	"help.start()" for a HTML browser interface to help.
Type	"q()" to quit R.

> dyn.load("test.so")
> .C("BT_demo",5)
Everything fine
[[1]]
[1] 5

> .C("BT_demo",5)

Process R segmentation fault (core dumped) at Wed Oct 27 17:42:05 1999


=============== Compiled with modified Rdefines.h ==========
R : Copyright 1999, The R Development Core Team
Version 0.65.1 Release (October 07, 1999)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type	"?license" or "?licence" for distribution details.

R is a collaborative project with many contributors.
Type	"?contributors" for a list.

Type	"demo()" for some demos, "help()" for on-line help, or
    	"help.start()" for a HTML browser interface to help.
Type	"q()" to quit R.

> dyn.load("test.so")
> .C("BT_demo",5)
Everything fine
[[1]]
[1] 5

> .C("BT_demo",5)
Everything fine
[[1]]
[1] 5

> .C("BT_demo",5)
Everything fine
[[1]]
[1] 5

> .C("BT_demo",5)
Everything fine
[[1]]
[1] 5

> q()
Save workspace image? [y/n/c]: n

Process R finished at Wed Oct 27 17:43:17 1999

--please do not edit the information below--

Version:
 platform = i686-unknown-linux
 arch = i686
 os = linux
 system = i686, linux
 status = Release
 major = 0
 minor = 65.1
 year = 1999
 month = October
 day = 07
 language = R

Search Path:
 .GlobalEnv, Autoloads, package:base
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._


Rdefines.h
Berwin Turlach