Re: [Rd] Segfault on ".C" registration via R_CMethodDef according to 'Writing R Extensions'.

From: Daniel Adler <dadler_at_uni-goettingen.de>
Date: Mon, 06 Feb 2012 16:42:21 +0100

Simon,

Thank you for the prompt and comprehensive explaination. Using the explicit array casts for types and style in all the variants previously mentioned works fine - no errors, warnings, segfaults. Great!
I suggest to add the "(R_NativePrimitiveArgType[4])" expression to the example in the manual.

Regards,
- Daniel

On Feb 6, 2012, at 3:47 PM, Simon Urbanek wrote:

> Daniel,
> 
> the code you are using is probably not what you intended - since there is no length information the compiler assumes you are filling the structure sequentially and thus the expected value is that for R_NativePrimitiveArgType* which has no length, so it can only be initialized with a scalar value, so you are setting
> 
> R_NativePrimitiveArgType* types = REALSXP
> 
> which is wrong as you are casing an integer into a pointer. Also that's why you get the warnings which are all valid:
> 
> ra.c:9: warning: braces around scalar initializer
> -- because it is interpeted as {REALSXP} hence superfluous braces
> 
> ra.c:9: warning: initialization makes pointer from integer without a cast
> -- because you're initializing  R_NativePrimitiveArgType* with an integer (REALSXP)
> 
> ra.c:9: warning: excess elements in scalar initializer
> -- because INTSXP, ... must be ignored since "types" can only be initialized with a scalar (pointer)
> 
> For what you intended, you're using variable-length array so you have to specify its length:
> 
> {"myC", (DL_FUNC) &myC, 4,  (R_NativePrimitiveArgType[4]) {REALSXP, INTSXP, STRSXP, LGLSXP}}
> 
> which will allocate extra static object (it has to because "types" is a pointer, not a fixed array) - so the effect is the same as using a static object.


> 
> Cheers,
> Simon
> 
> 
> 
> On Feb 6, 2012, at 8:27 AM, Daniel Adler wrote:
> 

>> Dear R List,
>>
>> I encountered a serious problem regarding the registration of ".C" when following the documentation "Writing R Extensions"
>> that leads to a segmentation fault (tested on windows and mac os x).
>>
>> The registration mechanism for ".C" routines via R_registerRoutines and
>> the R_CMethodDef structure has been enhanced recently with the
>> addition of two fields, one for type specification and the other for
>> the style (in, out, inout or irrelevant).
>>
>> According to the manual 'Writing R Extensions' of version 2.14.1
>> an example is given that specifies to use the fourth field (type information)
>> for definitions of C routines that use the ".C" calling convention:
>>
>> R_CMethodDef cMethods[] = {
>> {"myC", (DL_FUNC) &myC, 4, {REALSXP, INTSXP, STRSXP, LGLSXP}}, /* segfault! */
>> {NULL, NULL, 0}
>> };
>>
>> If I follow this example I get compiler warnings or errors (whether I use C or C++, respectively) and
>> a segmentation fault (in the case of C) when doing R CMD INSTALL, which seem to happen during testing.
>> See build log at the end of this e-mail.
>>
>> When removing the last field in the initializer list in order to register .C routines in the old way the segfault goes away:
>>
>> R_CMethodDef cMethods[] = {
>> {"myC", (DL_FUNC) &myC, 4}, /* works */
>> {NULL, NULL, 0}
>> };
>>
>> There are still warnings/segfault or an error when initializing the undocumented fifth entry (parameter passing style), e.g.
>>
>> R_CMethodDef cMethods[] = {
>> {"myC", (DL_FUNC) &myC, 4, {REALSXP, INTSXP, STRSXP, LGLSXP}, {R_ARG_IN, R_ARG_IN, R_ARG_IN, R_ARG_IN}, /* segfault! */
>> {NULL, NULL, 0}
>> };
>>
>> Using a C source, the warnings are:
>>
>> *** arch - i386
>> gcc -arch i386 -std=gnu99 -I/Library/Frameworks/R.framework/Resources/include -I/Library/Frameworks/R.framework/Resources/include/i386 -I/usr/local/include -fPIC -g -O2 -Wall -pedantic -c reg.c -o reg.o
>> reg.c:24: warning: braces around scalar initializer
>> reg.c:24: warning: (near initialization for ‘cMethods[0].types’)
>> reg.c:24: warning: initialization makes pointer from integer without a cast
>> reg.c:24: warning: excess elements in scalar initializer
>> reg.c:24: warning: (near initialization for ‘cMethods[0].types’)
>> reg.c:24: warning: excess elements in scalar initializer
>> reg.c:24: warning: (near initialization for ‘cMethods[0].types’)
>> reg.c:24: warning: excess elements in scalar initializer
>> reg.c:24: warning: (near initialization for ‘cMethods[0].types’)
>>
>>
>> Using C++, protecting the init/unload function prototypes and structure declarations via 'extern "C" { }', I get the following error:
>>
>> *** arch - i386
>> g++ -arch i386 -I/Library/Frameworks/R.framework/Resources/include -I/Library/Frameworks/R.framework/Resources/include/i386 -I/usr/local/include -fPIC -g -O2 -c reg.cpp -o reg.o
>> reg.cpp:30: error: braces around scalar initializer for type ‘R_NativePrimitiveArgType*’
>>
>> (line 24 is the point on the entry, while line 30 is the end of the overall array initialization list in C++).
>>
>> If I put the type and style (unsigned int and enum) arrays separately,
>> the build process works just fine. E.g.
>>
>> R_NativePrimitiveArgType types[] = {REALSXP, INTSXP, STRSXP, LGLSXP};
>> R_NativeArgStyle styles[] = { R_ARG_IN, R_ARG_IN, R_ARG_IN, R_ARG_IN };
>>
>> R_CMethodDef cMethods[] = {
>> {"myC", (DL_FUNC) &myC, 4, types, NULL}, /* works */
>> {"myC2", (DL_FUNC) &myC, 4, types, style}, /* works */
>> {NULL, NULL, 0}
>> };
>>
>> (Though I haven't tested the runtime behaviour yet.. but at least no segfault during R CMD INSTALL..)
>>
>> I wonder what is wrong with the static initializer lists?!
>>
>> I could imagine it has something to do with the standard compilance of the C/C++
>> compiler (due to the different behaviour warning or error during compilation).
>>
>> Anyway, going with the manual right now, the ordinary user will get warnings and
>> errors - at least on the systems that I have tested (recent version of Rtools/Windows 7
>> and Mac OS X 10.6 with gcc 4.2.1).
>> On Windows instead of a trace output, a window pops up during install to tell
>> about a process crash.
>>
>> - Daniel
>>
>> PS: If it helps, I could put up a test package online for further debugging.
>>
>> --- build log: ----------------------------------------------------------------
>>
>> ** testing if installed package can be loaded
>> *** arch - i386
>>
>> *** caught bus error ***
>> address 0xe, cause 'non-existent physical address'
>>
>> Traceback:
>> 1: dyn.load(file, DLLpath = DLLpath, ...)
>> 2: library.dynam(lib, package, package.lib)
>> 3: loadNamespace(package, c(which.lib.loc, lib.loc))
>> 4: doTryCatch(return(expr), name, parentenv, handler)
>> 5: tryCatchOne(expr, names, parentenv, handlers[[1L]])
>> 6: tryCatchList(expr, classes, parentenv, handlers)
>> 7: tryCatch(expr, error = function(e) { call <- conditionCall(e) if (!is.null(call)) { if (identical(call[[1L]], quote(doTryCatch))) call <- sys.call(-4L) dcall <- deparse(call)[1L] prefix <- paste("Error in", dcall, ": ") LONG <- 75L msg <- conditionMessage(e) sm <- strsplit(msg, "\n")[[1L]] w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], type = "w") if (is.na(w)) w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L], type = "b") if (w > LONG) prefix <- paste(prefix, "\n ", sep = "") } else prefix <- "Error : " msg <- paste(prefix, conditionMessage(e), "\n", sep = "") .Internal(seterrmessage(msg[1L])) if (!silent && identical(getOption("show.error.messages"), TRUE)) { cat(msg, file = stderr()) .Internal(printDeferredWarnings()) } invisible(structure(msg, class = "try-error", condition = e))})
>> 8: try({ ns <- loadNamespace(package, c(which.lib.loc, lib.loc)) dataPath <- file.path(which.lib.loc, package, "data") env <- attachNamespace(ns, pos = pos, dataPath = dataPath, deps)})
>> 9: library(pkg_name, lib.loc = lib, character.only = TRUE, logical.return = TRUE)
>> 10: withCallingHandlers(expr, packageStartupMessage = function(c) invokeRestart("muffleMessage"))
>> 11: suppressPackageStartupMessages(library(pkg_name, lib.loc = lib, character.only = TRUE, logical.return = TRUE))
>> 12: doTryCatch(return(expr), name, parentenv, handler)
>> 13: tryCatchOne(expr, names, parentenv, handlers[[1L]])
>> 14: tryCatchList(expr, classes, parentenv, handlers)
>> 15: tryCatch(expr, error = function(e) { call <- conditionCall(e) if (!is.null(call)) { if (identical(call[[1L]], quote(doTryCatch))) call <- sys.call(-4L) dcall <- deparse(call)[1L] prefix <- paste("Error in", dcall, ": ") LONG <- 75L msg <- conditionMessage(e) sm <- strsplit(msg, "\n")[[1L]] w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], type = "w") if (is.na(w)) w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L], type = "b") if (w > LONG) prefix <- paste(prefix, "\n ", sep = "") } else prefix <- "Error : " msg <- paste(prefix, conditionMessage(e), "\n", sep = "") .Internal(seterrmessage(msg[1L])) if (!silent && identical(getOption("show.error.messages"), TRUE)) { cat(msg, file = stderr()) .Internal(printDeferredWarnings()) } invisible(structure(msg, class = "try-error", condition = e))})
>> 16: try(suppressPackageStartupMessages(library(pkg_name, lib.loc = lib, character.only = TRUE, logical.return = TRUE)))
>> 17: tools:::.test_load_package("mylib", "/Users/dadler/Library/R/2.14/library")
>> aborting ...
>> sh: line 1: 75200 Bus error '/Library/Frameworks/R.framework/Resources/bin/R' --arch=i386 --no-save --slave < /var/folders/Lr/Lrh7GWILEqCwHkyF1MdauE+++TI/-Tmp-//RtmpDqusSN/file1259d93ec2eb
>> *** arch - x86_64
>>
>> ______________________________________________
>> R-devel_at_r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>>
>

R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Mon 06 Feb 2012 - 15:54:56 GMT

This quarter's messages: by month, or sorted: [ by date ] [ by thread ] [ by subject ] [ by author ]

All messages

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Mon 06 Feb 2012 - 20:50:13 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.

list of date sections of archive