错误: C 堆栈的使用过于接近限制

我尝试在 R 语言中运行一些相当深入的递归代码,结果总是出现这样的错误:

错误: C 堆栈的使用过于接近限制

我从 CStack_info()得到的输出是:

Cstack_info()
size    current  direction eval_depth
67108864       8120          1          2

我的机器上有很多内存,我只是想知道如何增加 R 的 CStack。

编辑: 有人要求一个可重复的例子。下面是一些导致问题的基本示例代码。运行 f (1,1)几次就会得到错误。注意,我已经设置了—— max-ppsize = 500000和 options (expression = 500000) ,所以如果您没有设置这些选项,您可能会得到关于这两个选项之一的错误。正如你所看到的,递归可以深入到这里,我不知道如何让它始终如一地工作。谢谢。

f <- function(root=1,lambda=1) {
x <- c(0,1);
prob <- c(1/(lambda+1),lambda/(lambda+1));
repeat {
if(root == 0) {
break;
}
else {
child <- sample(x,2,replace=TRUE,prob);
if(child[1] == 0 && child[2] == 0) {
break;
}
if(child[1] == 1) {
child[1] <- f(root=child[1],lambda);
}
if(child[2] == 1 && child[1] == 0) {
child[2] <- f(root=child[2],lambda);
}
}
if(child[1] == 0 && child[2] == 0) {
break;
}
if(child[1] == 1 || child[2] == 1) {
root <- sample(x,1,replace=TRUE,prob);
}
}
return(root)
}
150308 次浏览

The stack size is an operating system parameter, adjustable per-process (see setrlimit(2)). You can't adjust it from within R as far as I can tell, but you can adjust it from the shell before starting R, with the ulimit command. It works like this:

$ ulimit -s # print default
8192
$ R --slave -e 'Cstack_info()["size"]'
size
8388608

8388608 = 1024 * 8192; R is printing the same value as ulimit -s, but in bytes instead of kilobytes.

$ ulimit -s 16384 # enlarge stack limit to 16 megs
$ R --slave -e 'Cstack_info()["size"]'
size
16777216

To make a permanent adjustment to this setting, add the ulimit command to your shell startup file, so it's executed every time you log in. I can't give more specific directions than that, because it depends on exactly which shell you have and stuff. I also don't know how to do it for logging into a graphical environment (which will be relevant if you're not running R inside a terminal window).

I suspect that, regardless of stack limit, you'll end up with recursions that are too deep. For instance, with lambda = Inf, f(1) leads to an immediate recursion, indefinitely. The depth of the recursion seems to be a random walk, with some probability r of going deeper, 1 - r of finishing the current recursion. By the time you've hit the stack limit, you've made a large number of steps 'deeper'. This implies that r > 1 / 2, and the very large majority of time you'll just continue to recurse.

Also, it seems like it is almost possible to derive an analytic or at least numerical solution even in the face of infinite recursion. One can define p as the probability that f(1) == 1, write implicit expressions for the 'child' states after a single iteration, and equate these with p, and solve. p can then be used as the chance of success in a single draw from a binomial distribution.

This happened to me for a completely different reason. I accidentally created a superlong string while combining two columns:

output_table_subset = mutate(big_data_frame,
combined_table = paste0(first_part, second_part, col = "_"))

instead of

output_table_subset = mutate(big_data_frame,
combined_table = paste0(first_part, second_part, sep = "_"))

Took me for ever to figure it out as I never expected the paste to have caused the problem.

As Martin Morgan wrote... The problem is that you get too deep inside of recursion. If the recursion does not converge at all, you need to break it by your own. I hope this code is going to work, because It is not tested. However at least point should be clear here.

f <- function(root=1,lambda=1,depth=1) {
if(depth > 256){
return(NA)
}
x <- c(0,1);
prob <- c(1/(lambda+1),lambda/(lambda+1));
repeat {
if(root == 0) {
break;
} else {
child <- sample(x,2,replace=TRUE,prob);
if(child[1] == 0 && child[2] == 0) {
break;
}
if(child[1] == 1) {
child[1] <- f(root=child[1],lambda,depth+1);
}
if(child[2] == 1 && child[1] == 0) {
child[2] <- f(root=child[2],lambda,depth+1);
}
}
if(child[1] == NA | child[2] == NA){
return NA;
}
if(child[1] == 0 && child[2] == 0) {
break;
}
if(child[1] == 1 || child[2] == 1) {
root <- sample(x,1,replace=TRUE,prob);
}
}
return(root)
}

I encountered the same problem of receiving the "C stack usage is too close to the limit" error (albeit for another application than the one stated by user2045093 above). I tried zwol's proposal but it didn't work out.

To my own surprise, I could solve the problem by installing the newest version of R for OS X (currently: version 3.2.3) as well as the newest version of R Studio for OS X (currently: 0.99.840), since I am working with R Studio.

Hopefully, this may be of some help to you as well.

One issue here can be that you're calling f inside itself

plop <- function(a = 2){
pouet <- sample(a)
plop(pouet)
}
plop()
Erreur : évaluations trop profondément imbriquées : récursion infinie / options(expressions=) ?
Erreur pendant l'emballage (wrapup) : évaluations trop profondément imbriquées : récursion infinie / options(expressions=) ?

This error is not due to memory it is due to recursion. A function is calling itself. This isn't always obvious from examining the definition of only one function. To illustrate the point, here is a minimal example of 2 functions that call each other:

change_to_factor <- function(x){
x <- change_to_character(x)
as.factor(x)
}


change_to_character <- function(x){
x <- change_to_factor(x)
as.character(x)
}


change_to_character("1")

Error: C stack usage 7971600 is too close to the limit

The functions will continue to call each other recursively and will theoretically never complete, even if you increase the limit it will still be exceeded. It is only checks within your system that prevent this from occurring indefinitely and consuming all of the compute resources of your machine. You need to alter the functions to ensure that they won't indefinitely call itself (or each other) recursively.

Another way to cause the same problem:

library(debug)
mtrace(lapply)

The recursive call isn't as obvious here.

If you're using plot_ly check which columns you are passing. It seems that for POSIXdt/ct columns, you have to use as.character() before passing to plotly or you get this exception!

For everyone's information, I am suddenly running into this with R 3.6.1 on Windows 7 (64-bit). It was not a problem before, and now stack limits seem to be popping up everywhere, when I try to "save(.)" data or even do a "save.image(.)". It's like the serialization is blowing these stacks away.

I am seriously considering dropping back to 3.6.0. Didn't happen there.

Mine is perhaps a more unique case, but may help the few who have this exact problem:

My case has absolutely nothing to do with space usage, still R gave the:
C stack usage is too close to the limit

I had a defined function which is an upgrade of the base function:

saveRDS()

But,
Accidentally, this defined function was called saveRDS() instead of safe_saveRDS().
Thus, past that definition, when the code got to the line wihch actually uses saveRDS(...) (which calls the original base version, not the upgraded one), it gave the above error and crushed.

So, if you're getting that error when calling some saving function, see if you didn't accidentally run over it.

I often include a commented-out source("path/to/file/thefile.R") line at the top of an R script, e.g. thefile.R, so I can easily copy-paste this into the terminal to run it. I get this error if I forget to comment out the line, since running the file runs the file, which runs the file, which runs the file, ...

If that is the cause, the solution is simple: comment out the line.

Not sure if we re listing issues here but it happened to me with leaflet(). I was trying to map a dataframe in which a date column was of class POSIXlt. Changing back to POSIXct solved the issue.

On Linux, I have permanently increased the size of the stack and memlock memories by doing so :

sudo vi /etc/security/limits.conf

Then, add the following lines at the end of the file.

* soft memlock unlimited
* hard memlock unlimited


* soft stack unlimited
* hard stack unlimited

Here is how I encountered this error message. I met this error message when I tried to print a data.table in the console. It turned out it was because I mistakenly made a super super long string (by using collapse in paste() when I shouldn't) in a column.

The package caret has a function called createDataPartition that always results in error when the dataset to be partitioned has more than 1m rows. Just for your info.