[Rd] Bug ? mine or ? in R core

Michael Lapsley mlapsley@ndirect.co.uk
Sat, 1 Apr 2000 19:18:09 +0100


Dear R Gurus,

I would very much appreciate some help with this code snippit
from my RODBC package.

R crashes or exhibits bizarre behaviour when repeatedly fetching
large numbers of rows.

Examples:

> odbcFetchRows(0,max=50000)->xx
> odbcFetchRows(0,max=50000)->xx
> odbcFetchRows(0,max=50000)->xx
> odbcFetchRows(0,max=50000)->xx
> odbcFetchRows(0,max=50000)->xx
3rd arg (table) not of type VECSXP, from R_HashGet
Segmentation fault (core dumped)


> odbcFetchRows(0,max=100000)->xx
> odbcFetchRows(0,max=100000)->xx
Segmentation fault (core dumped)

> odbcFetchRows(0,max=50000)
...
...[49996,] "Some dummy data"
[49997,] "Some dummy data"
[49998,] "Some dummy data"
[49999,] "Some dummy data"
[50000,] "Some dummy data"

$stat
[1] 1

> odbcFetchRows(0,max=50000)
Error in odbcFetchRows(0, max = 50000) : can not set length of non-vector
> odbcFetchRows(0,max=50000)

[49998,] "Some dummy data"
[49999,] "Some dummy data"
[50000,] "Some dummy data"

$stat
[1] 1

> odbcFetchRows(0,max=50000)
Segmentation fault (core dumped)

(This is using a hacked version that does not actually fetch rows
from the database to save time).

Using the C that I distilled out (see below) to remove all
dependencies on sql/odbc I get something even more bizarre:

> odbcFetchRows(0,max=50000)->xx
> odbcFetchRows(0,max=50000)->xx
> odbcFetchRows(0,max=50000)->xx
Segmentation fault (core dumped)

but

> odbcFetchRows(0,max=25000)->xx
> odbcFetchRows(0,max=25000)->xx
> odbcFetchRows(0,max=25000)->xx
> odbcFetchRows(0,max=25000)->xx
Error: corrupted options list
Error: corrupted options list
Error: corrupted options list
Error: corrupted options list
Error: corrupted options list
Error: corrupted options list
Error: corrupted options list
Error: corrupted options list
.....
(endless loop needing killing)

I have stared at this for ages and cannot see the bug?  Is it me
or is there a problem in garbage collection or elsewhere?

Thanks in advance for any enlightenment.


Michael

-----------------------------------------------------------------

/* RODBC low level interface : crash function
 *
 * crash.c
 *
 */
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>


#include <Rinternals.h>
#include <Rdefines.h>


#define DBG(x,y) if(debug >= x) printf("%s\n",y)

/*******************************************************************************/
/* Replacement callee for odbcFetchRows to demonstate bug.                     */
/* Independant of sql/odbc                                                     */
/* Compile with                                                                */
/* cc -g  -Wall -I/usr/local/src/R-1.0.0/include/  -o crash.o -c crash.c       */
/* gcc -shared -g -Wall      -o crash.so  crash.o                              */
/* mv crash.so /usr/local/src/R-1.0.0/library/RODBC/libs/RODBC.so              */
/* then                                                                        */
/* $R -q                                                                       */
/* >library(RODBC)                                                             */
/* >odbcFetchRows(0,max=50000)                                                 */
/* and repeat till crashes.                                                    */
/*                                                                             */
/* Note that the loop will never exit unless max is specified.                 */
/*                                                                             */
/* Designed to work with RODBC-0.6.1a                                          */
/* Caller looks like:                                                          */
/*                                                                             */
/* "odbcFetchRows"<-                                                           */
/* function(channel,max=0,transposing=F,buffsize=1000,debug=0)                 */
/* {                                                                           */
/*         erg<-.Call("RODBCFetchRows",as.integer(channel),max=as.real(max),   */
/*                         transposing=as.logical(transposing),                */
/*                         buffsize=as.real(buffsize),debug=as.integer(debug)) */
/*         return(erg)                                                         */
/*         }                                                                   */
/*                                                                             */
/*                                                                             */
/*******************************************************************************/
SEXP RODBCFetchRows(SEXP sock,SEXP max,SEXP tx,SEXP bs,SEXP dbg)
{
SEXP data,t_data,names,ans,stat,dim;
int 	status=1,
	i,				/* col counter */
	NCOLS,
	channel=INTEGER(sock)[0],	/* not used here */
	debug=INTEGER(dbg)[0],
	transposing=(int)LOGICAL(tx)[0];	/*true if transposing, not used here*/

long maximum=(long)REAL(max)[0];

long 	j=1,k=1,			/* row counters*/
	buffsize=(long)REAL(bs)[0],	/* prealloc if row count NA*/
	length,offset,t_offset;		/* counts into output buf*/


NCOLS=1;
PROTECT(ans=NEW_LIST(2)); /*create answer [0] = data, [1]=stat */
PROTECT(stat=NEW_INTEGER(1)); /* numeric status vector */
PROTECT(data=NEW_CHARACTER(buffsize));
while(1){
	for (i=1; i<= NCOLS; i++){
			offset=((i-1)*maximum)+(j-1);
		}
	  DBG(2,"writing to data");
	  STRING(data)[offset]=COPY_TO_USER_STRING("Some dummy data");
		if(offset +NCOLS >= buffsize){
			DBG(1,"reallocating space");
			length=length(data);
			buffsize=length+buffsize;
			SET_LENGTH(data,buffsize);
		}
	j++;
	if(maximum && j>maximum)
		break;
}	

/* transpose it */
DBG(1,"trimming");
SET_LENGTH(data,j*NCOLS); /* trim down buffer*/

INTEGER(stat)[0]=status;
PROTECT(dim=NEW_INTEGER(2));


INTEGER(dim)[1]=NCOLS;
INTEGER(dim)[0]=length(data)/NCOLS;


DBG(2,"writing dim to data");
SET_DIM(data,dim);
DBG(2,"writing to ans 0");
VECTOR(ans)[0]=data;
DBG(2,"writing to ans 1");
VECTOR(ans)[1]=stat;
DBG(3,"protecting names");
PROTECT(names=NEW_CHARACTER(2));                                  
DBG(2,"writing to names 0");
STRING(names)[0]=COPY_TO_USER_STRING("data");                    
DBG(2,"writing to names 1");
STRING(names)[1]=COPY_TO_USER_STRING("stat");                   
DBG(2,"writing to ans");
SET_NAMES(ans,names);                                          
UNPROTECT(5);
return ans;
}

/****************************************/
/* Just a dummy to allow library(RODBC) */
/****************************************/
void RODBCInit()
{
}
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
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
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._