On 4/30/23 06:05, Michael Milton wrote:
Hi Tomas, thanks for the reply. I played with some of the factors you mentioned like allocating more INTSXP of the same size as vec_1, to little success. The thing that actually "worked" and caused a segfault, was simply allocating a larger vector the first time. 100 elements seemed to do it, but 10 or less elements almost never caused a segfault. Is there some other part of memory that small vectors are allocated that would prevent them being collected? Might this relate to the Ncells vs Vcells?distinction?
I don't think it would be directly related (these are both vectors), but I don't remember all the details. If you are interested in how exactly the allocator works, I suggest reading memory.c - the sources are quite small and easy to read. There is some external fragmentation which limits what can be re-used. You could in principle force re-use by using objects of the same size and type (but the number might have to be large, maybe it wasn't large enough), or a single larger object (as you did). It doesn't make sense speculating more without reading the code, instrumenting and possibly debugging, if you want to find out exactly what is happening in your situation. Tomas
z = inline::cfunction(body="
? ? SEXP vec_1 = Rf_allocVector(INTSXP, 100); ? ? SEXP vec_2 = Rf_allocVector(VECSXP, 3); ? ? SET_VECTOR_ELT(vec_2, 1, vec_1); ")
z()
NULL Warning message: In z() : your C program does not return anything!
gctorture(TRUE) z()
?*** caught segfault ***
address 0x55a68ce57f90, cause 'memory not mapped'
Traceback:
?1: doWithOneRestart(return(expr), restart)
?2: withOneRestart(expr, restarts[[1L]])
?3: withRestarts({ ?.Internal(.signalCondition(simpleWarning(msg,
call), msg, ? ? call)) ? ?.Internal(.dfltWarn(msg, call))},
muffleWarning = function() NULL)
?4: .signalSimpleWarning("your C program does not return anything!", ?
? base::quote(z()))
?5: .Primitive(".Call")(<pointer: 0x7f2a02572160>)
?6: z()
On Sun, Apr 30, 2023 at 4:04?AM Tomas Kalibera
<tomas.kalibera at gmail.com> wrote:
On 4/29/23 19:26, Michael Milton wrote:
> I'm trying to learn about R's PROTECT system. To that end I've
tried to
> create an example of C code that doesn't protect anything. I was
hoping it
> would either segfault from trying to access deallocated memory,
or maybe
> print out nonsense results because the unprotected memory got
overwritten,
> but I can't make either happen.
>
> Here's my current code (all in R, using the inline package for
simplicity):
>
>> gctorture(TRUE)
>> z = inline::cfunction(body="
>? ? ? SEXP vec_1 = Rf_ScalarInteger(99);
>? ? ? SEXP vec_2 = Rf_allocVector(VECSXP, 10);
>? ? ? SET_VECTOR_ELT(vec_2, 1, vec_1);
>? ? ? Rf_PrintValue(vec_2);
> ")
>
> My thinking was that, with torture mode enabled, the allocation
of vec_2
> should ensure that vec_1 is collected, and then trying to put it
into vec_2
> and then print it would then fail. But it consistently prints 99
in the
> list's second element.
>
> Why does this code not have issues? Alternatively, is there a
simpler
> example of C code that demonstrates missing PROTECT calls?
It is not guaranteed that a PROTECT error will always lead to memory
corruption or a crash in all executions of a program, not even with
gctorture.
To increase the chances, you can instruct gctorture to run the gc
more
often (but the execution would be slower). You can build R with
strict
write barrier checking (see e.g. Writing R Extensions, look for
gctorture) to make it more likely errors will be detected. There is
always a tradeoff between this probability and slowdown of the
execution. In theory we could invalidate all unreachable objects at
every allocation, but that would be so slow that we could not test
any
programs in practice.
Then, not every piece of memory can be used by any allocation, due to
how the memory allocator and gc works. If you need to provoke an
error
e.g. for educational purposes, perhaps chances would be higher if you
allocate an object of the same type and size as the one not
protected in
error.
You can also play with R sources - e.g. introduce a PROTECT error
into
some key part of the R interpreter, it should not be too hard to
trigger
that via make check-devel.
Best
Tomas
>
>? ? ? ?[[alternative HTML version deleted]]
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel