This was posted so it was not lost. Probably no one felt like giving you free technical support. You are using the Rdefines.h macros with which few of use are familiar. But you will find the native version, lengthgets, used to extend vectors in several places in the R sources. I don't understand your code (the real code is hidden behind an obscuring layer of macros), but this sounds very like a protection problem. In any case, lengthgets just reallocates and copies and it probably more efficient to do that yourself. On Fri, 12 Dec 2003, Jim Java wrote:> Hi folks. I posted this question a few days ago, but maybe it got lost > because of the code I included with it. I'm having a problem using the > SET_LENGTH() macro in an R extension I'm writing in C++. In a function > within the extension I use SET_LENGTH() to resize R vectors so as to > allow the concatenation of single values onto the vectors -- it's a > "push back" function to append values onto the end of a vector. > However, when I use this function to push back a large number of > values one at a time, Rgui.exe (I'm working with R 1.8.1 in Windows > XP) crashes from an Access Violation; if, however, I pre-allocate > space (is the space actually pre-allocated?) for the vector (say with > NEW_INTEGER(n) rather than NEW_INTEGER(0)) and insert values into the > allocated slots, the code works fine. If you'd like to see some test > code, I've already posted it here: > > https://www.stat.math.ethz.ch/pipermail/r-help/2003-December/041871.html > > Here's my question, then: Is SET_LENGTH() the appropriate way to > create space for tacking values onto the end of an R-vector in C++, or > should I be trying to tack them on in some other way?-- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
Hi folks. I posted this question a few days ago, but maybe it got lost because of the code I included with it. I'm having a problem using the SET_LENGTH() macro in an R extension I'm writing in C++. In a function within the extension I use SET_LENGTH() to resize R vectors so as to allow the concatenation of single values onto the vectors -- it's a "push back" function to append values onto the end of a vector. However, when I use this function to push back a large number of values one at a time, Rgui.exe (I'm working with R 1.8.1 in Windows XP) crashes from an Access Violation; if, however, I pre-allocate space (is the space actually pre-allocated?) for the vector (say with NEW_INTEGER(n) rather than NEW_INTEGER(0)) and insert values into the allocated slots, the code works fine. If you'd like to see some test code, I've already posted it here: https://www.stat.math.ethz.ch/pipermail/r-help/2003-December/041871.html Here's my question, then: Is SET_LENGTH() the appropriate way to create space for tacking values onto the end of an R-vector in C++, or should I be trying to tack them on in some other way? Thanks again! -- Jim Java
---------- Original Message ---------------------------------- From: Prof Brian Ripley <ripley at stats.ox.ac.uk> Date: Fri, 12 Dec 2003 04:34:31 +0000 (GMT)>This was posted so it was not lost. Probably no one felt like giving you >free technical support.Thanks for your answer -- I wasn't trying to scam anything for free, just trying to see if anyone from the Core Team could give me some advice on this problem, which seems like something that someone would've run into before. I've been trying to get some code done quickly (I've only been involved in R development for about a month) and was hoping there might be a simple answer to my problem that I'd overlooked. Since there isn't a simple answer, I will take the time to go through the R source code to see whether I can figure out what I must change in my code to accord with the way R does things. It's my fault.>You are using the Rdefines.h macros with which few of use are familiar. >But you will find the native version, lengthgets, used to extend vectors >in several places in the R sources. I don't understand your code (the >real code is hidden behind an obscuring layer of macros), but this sounds >very like a protection problem.I will look at the source for lengthgets(). If mine's a protection problem, though, I must've missed an error in my test code, because I made it as simple as possible so as to reproduce the Access Violation, with great attention to protecting the created SEXP's correctly. I will test the code in Linux, too, to see whether a similar error happens.>In any case, lengthgets just reallocates and copies and it probably more >efficient to do that yourself.If lengthgets() finally just realloc()s the vectors I've created, then what I'm doing is quite inefficient. If you have the patience for another question, Are R vectors represented as linked lists in C or as simple arrays? I'm asking because I wonder how c() is implemented; I'd guess I should call whatever c() calls within the R code to add values onto vectors, but I'm not sure exactly what c() does there. If the answer is "You need to study the R source yourself" that's okay; I'm new here and don't wish to try to take more than I'm entitled to, nor do I wish to task the beneficence of the founders! Cheers, Jim Java
[Jim Java]>Hi folks. I posted this question a few days ago, but maybe it got >lost because of the code I included with it. I'm having a problem >using the SET_LENGTH() macro in an R extension I'm writing in C++. >In a function within the extension I use SET_LENGTH() to resize R >vectors so as to allow the concatenation of single values onto the >vectors -- it's a "push back" function to append values onto the >end of a vector. However, when I use this function to push back a >large number of values one at a time, Rgui.exe (I'm working with R >1.8.1 in Windows XP) crashes from an Access Violation; if, however, >I pre-allocate space (is the space actually pre-allocated?) for the >vector (say with NEW_INTEGER(n) rather than NEW_INTEGER(0)) and >insert values into the allocated slots, the code works fine. If >you'd like to see some test code, I've already posted it here: > >https://www.stat.math.ethz.ch/pipermail/r-help/2003-December/041871.html > >Here's my question, then: Is SET_LENGTH() the appropriate way to >create space for tacking values onto the end of an R-vector in C++, >or should I be trying to tack them on in some other way?[Brian Ripley]>You UNPROTECT before calling lengthgets, and that is I think part >of your problem. You need to use REPROTECT...[Jim Java] This problem is solved, so I want to post a follow-up for reference in the archives. My thanks to Prof. Ripley for helping me out: the problem was indeed in using UNPROTECT before lengthgets() rather than using REPROTECT afterwards. My revised test code is listed below, also for reference. <CPP Code> SEXP R_SimplePushBackTest(SEXP args) { SEXP arg1, arg2, int_vect; PROTECT(arg1 = AS_INTEGER(CADR(args))); int n_reps = INTEGER_POINTER(arg1)[0]; PROTECT(arg2 = AS_LOGICAL(CADDR(args))); bool full_alloc = (LOGICAL_POINTER(arg2)[0] ? true : false); PROTECT_INDEX int_vect_pindex; if (full_alloc) PROTECT_WITH_INDEX(int_vect = NEW_INTEGER(n_reps), &int_vect_pindex); else PROTECT_WITH_INDEX(int_vect = NEW_INTEGER(0), &int_vect_pindex); for (int i = 0; i < n_reps; ++i) { Rprintf(" ** Iteration %d:\n", i + 1); if (full_alloc) INTEGER_POINTER(int_vect)[i] = i; else { // This works now! -- SET_LENGTH(int_vect, GET_LENGTH(int_vect) + 1); REPROTECT(int_vect, int_vect_pindex); INTEGER_POINTER(int_vect)[GET_LENGTH(int_vect) - 1] = i; } } SEXP out, names, cls; PROTECT(out = NEW_LIST(1)); SET_VECTOR_ELT(out, 0, int_vect); PROTECT(names = NEW_CHARACTER(1)); SET_STRING_ELT(names, 0, COPY_TO_USER_STRING("integer.vector")); SET_NAMES(out, names); PROTECT(cls = NEW_CHARACTER(1)); SET_STRING_ELT(cls, 0, COPY_TO_USER_STRING("pushback")); classgets(out, cls); UNPROTECT(6); return out; } </CPP Code> <R Code> nreps=50000 allocate=FALSE sink("pushback_test.txt") test.pushback=.External("R_SimplePushBackTest", as.integer(nreps), as.logical(allocate)) print(test.pushback) sink() </R Code>