多线程时为什么Rcout和Rprintf会出现stack limit error?

Why does Rcout and Rprintf cause stack limit error when multithreading?

所以在下面的代码中,我使用 std::thread() 来报告程序进度,该示例已更改为以不合理的间隔报告,并显示一条无信息的消息,以证明该问题。

#include <Rcpp.h>
#include <thread>
#include <chrono>
#include <atomic>
using namespace Rcpp;

void reporter(const std::atomic<bool> &running) {
    while (running) {
        Rprintf( "Program running...\n" );
        std::this_thread::sleep_for(std::chrono::microseconds(10));
    }
}

// [[Rcpp::export]]
void example() {
    int i = 1;
    std::atomic<bool> running{true};

    std::thread reporter_thread(
        [&] () { reporter(running); }
    );

    while (true) {
        i++;
        i--;
    }


    return;
}

在我的 2017 款 MacBook Pro 上,这恰好在第 93 次打印时触发了 stack usage is too close to the limit 崩溃。如果我更改为 Rprintf,这也会崩溃,但据我所知,std::cout 是免疫的。

我可以更改代码,以便在父线程中进行打印,并在生成的线程中切换一个标志,这似乎也可以避免崩溃。

#include <Rcpp.h>
#include <thread>
#include <chrono>
#include <atomic>
using namespace Rcpp;

void reporter(const std::atomic<bool> &running, std::atomic<bool> &print_message) {
    while (running) {
        std::this_thread::sleep_for(std::chrono::microseconds(10));
        print_message = true;
    }
}

// [[Rcpp::export]]
void example() {
    int i = 1;
    std::atomic<bool> running{true};
    std::atomic<bool> print_message{true};

    std::thread reporter_thread(
        [&] () { reporter(running, print_message); }
    );

    while (true) {
        i++;
        i--;
        if (print_message)
            Rprintf( "Program running...\n" );
            print_message = false;
    }


    return;
}

所以我有两个问题:

  1. 为什么第一个版本会导致崩溃。
  2. 第二个版本能保证安全吗?

关于你的第一个例子 Writing R Extensions 不得不说:

Calling any of the R API from threaded code is ‘for experts only’: they will need to read the source code to determine if it is thread-safe. In particular, code which makes use of the stack-checking mechanism must not be called from threaded code.

我会远离在线程代码中调用 R API 函数。我不确定你的第二个例子,但会先寻找现有的解决方案,例如http://gallery.rcpp.org/articles/using-rcppprogress/