From simon.urbanek at r-project.org  Fri Feb 11 22:53:26 2011
From: simon.urbanek at r-project.org (Simon Urbanek)
Date: Fri, 11 Feb 2011 16:53:26 -0500
Subject: [Rd] Writting my own package - 64 bit problem with
	R_GetCCallable
In-Reply-To: <AANLkTi=h3G=orR7oQRkRw7RxJSGafPnKg+BD0nZ0qM6i@mail.gmail.com>
References: <AANLkTi=h3G=orR7oQRkRw7RxJSGafPnKg+BD0nZ0qM6i@mail.gmail.com>
Message-ID: <8BEAD894-6D29-436B-A48D-3670F8D17E73@r-project.org>

Ryan,

On Feb 11, 2011, at 4:29 PM, Ryan King wrote:

> Hello list,
> I've been working on a package of my own.  It works fine on the 32bit
> linux machines that I've tested it on.  Someone using 64bit ubuntu
> wanted to try it, and surprising segfaults happened.  My test code
> results in no segfault, errors, or leaks from my calls when run under
> valgrind (I recompiled R with the level 2 valgrind instruments).  R
> and packages are compiled from source, so this is hopefully not a
> debian/ubuntu issue.  I'm totally stumped and hoping that this is a
> silly / common 32 to 64 bit transition issue.
> 
> The problem seems to come when I attempt to access a function
> registered by the Matrix package.  During compilation (on 64 bit only)
> I get the ominous:
> 
> --------------
> slim_stolen_from_matrix.c: In function ?R_as_cholmod_sparse?:
> slim_stolen_from_matrix.c:36: warning: implicit declaration of
> function ?R_GetCCallable?
> slim_stolen_from_matrix.c:36: warning: cast to pointer from integer of
> different size


This is the key issue - you're missing the declaration of R_GetCCallable() as the compiler tells you, so the compiler assumes "int" as the return value. However, int is only 32-bit so it won't hold a 64-bit pointer and hence you're in trouble.

All you really need is

#include <R_ext/Rdynload.h>

before you use R_GetCCallable and hopefully your issues should go away.

Note that your bug is there even in 32-bit -- you will see " implicit declaration of function" in any case -- it just is not fatal, incidentally. It is a good idea to listen to the compiler ... ;).

Cheers,
Simon


> --------------
> 
> The function in question is an identical copy of Matrix's
> M_as_cholmod_sparse, reproduced below
> 
> --------------
> CHM_SP
> R_as_cholmod_sparse(CHM_SP ans, SEXP x, Rboolean check_Udiag, Rboolean
> sort_in_place)
> {
>    static CHM_SP(*fun)(CHM_SP,SEXP,Rboolean,Rboolean)= NULL;
>    if(fun == NULL)
> 	fun = (CHM_SP(*)(CHM_SP,SEXP,Rboolean,Rboolean))
> 	    R_GetCCallable("Matrix", "as_cholmod_sparse");
>    return fun(ans, x, check_Udiag, sort_in_place);
> }
> --------------
> 
> I made this duplicate function since using Matrix's #include stubs
> conflicts with my copy of the CHOLMOD library (I need some functions
> Matrix doesn't make public).
> 
> When run, the code gives the following segfault when it reaches te
> first call to that function:
> 
> --------------
> Program received signal SIGSEGV, Segmentation fault.
> 0xfffffffff54314e2 in ?? ()
> *** caught segfault ***
> address 0xfffffffff54314e2, cause 'memory not mapped'
> --------------
> 
> As mentioned above, under valgrind the segault doesn't happen, but in
> GDB, the function pointer can be seen to have some problem.  In 64 bit
> --------------
> 35              fun = (CHM_SP(*)(CHM_SP,SEXP,Rboolean,Rboolean))
> (gdb) p fun
> $1 = (CHM_SP (*)(CHM_SP, SEXP, Rboolean, Rboolean)) 0
> (gdb) n
> 37          return fun(ans, x, check_Udiag, sort_in_place);
> (gdb) p fun
> $2 = (CHM_SP (*)(CHM_SP, SEXP, Rboolean, Rboolean)) 0xfffffffff54314e2
> --------------
> 
> vs 32bit
> --------------
> (gdb) p fun
> $1 = (CHM_SP (*)(CHM_SP, SEXP, Rboolean, Rboolean)) 0xb72a3ec0
> <as_cholmod_sparse>
> --------------
> 
> I've never done 64 bit development, so I don't know what I've probably
> done wrong.  I don't see an intermediate cast to an int to mess it up.
> Checking the pointer sizeof's seems like R_GetCCallable's return
> should be the same size as the function pointer.
> 
> --------------
> (gdb) p sizeof(void*)
> $5 = 8
> (gdb) p sizeof(CHM_SP*)
> $6 = 8
> (gdb) p sizeof(CHM_SP)
> $7 = 8
> (gdb) p sizeof(SEXP)
> $8 = 8
> (gdb) p sizeof(CHM_SP(*))
> $9 = 8
> (gdb) p sizeof(DL_FUNC)
> $10 = 8
> (gdb) p sizeof(DL_FUNC*)
> $11 = 8
> --------------
> 
> The function is invoked by
> ----------
> fitholder->Zt = R_as_cholmod_sparse
> ((CHM_SP)malloc(sizeof(cholmod_sparse)), Zt, TRUE, FALSE);
> -----------
> 
> where Zt is a SEXP pointing to a Matrix-class sparse matrix passed by
> .Call from R.  CHM_SP is a typedef'd pointer to a cholmod_sparse
> 
> 
> 
>> sessionInfo()
> R version 2.12.1 (2010-12-16)
> Platform: x86_64-unknown-linux-gnu (64-bit)
> 
> locale:
> [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
> [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
> [5] LC_MONETARY=C              LC_MESSAGES=en_US.UTF-8
> [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
> [9] LC_ADDRESS=C               LC_TELEPHONE=C
> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
> 
> attached base packages:
> [1] stats     graphics  grDevices utils     datasets  methods   base
> 
> other attached packages:
> [1] emmpat_0.001       Matrix_0.999375-46 lattice_0.19-13
> 
> loaded via a namespace (and not attached):
> [1] grid_2.12.1
> 
> 
> Ryan King
> University of Chicago
> Dept. Health Studies
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
> 
> 



[Rd] Writting my own package - 64 bit problem with R_GetCCallable
Simon Urbanek