Windows 和 Mac 之间 Rcpp::List 的长度不同

问题描述 投票:0回答:1

我正在检查

Rcpp::List
对象的长度,并注意到我在 Windows 上得到的结果与在 Mac 上不同。

C++代码

这是我的 C++ 代码,位于文件

"test.cpp"
中。我有一个
Data
类,其构造函数采用
Rcpp::List
并提取其名为
"constraints"
的元素。接下来,我有一个函数
foo
,它构造一个
Data
元素,提取
constraints
的长度,然后返回它。

#include <Rcpp.h>
using namespace Rcpp;

struct Data {
  Data(List data) :
  constraints { as<List>(data["constraints"]) } {}
  ~Data() = default;
  
  const List constraints;
};

// [[Rcpp::export]]
int foo(List dat) {
  Data dd {dat};
  int result = dd.constraints.length();
  return result;
}

在 Mac 上的 R 中运行的结果

这是我的会议:

> sessionInfo()
R version 4.3.2 RC (2023-10-30 r85440)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Sonoma 14.1.2

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: Europe/Oslo
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] vctrs_0.6.4       cli_3.6.1         knitr_1.45        rlang_1.1.2       xfun_0.41         processx_3.8.2   
 [7] purrr_1.0.2       styler_1.10.2     glue_1.6.2        clipr_0.8.0       htmltools_0.5.7   ps_1.7.5         
[13] fansi_1.0.5       rmarkdown_2.25    R.cache_0.16.0    evaluate_0.23     tibble_3.2.1      fastmap_1.1.1    
[19] yaml_2.3.7        lifecycle_1.0.4   compiler_4.3.2    fs_1.6.3          Rcpp_1.0.11.2     pkgconfig_2.0.3  
[25] rstudioapi_0.15.0 R.oo_1.25.0       R.utils_2.12.3    digest_0.6.33     R6_2.5.1          reprex_2.0.2     
[31] utf8_1.2.4        pillar_1.9.0      callr_3.7.3       magrittr_2.0.3    R.methodsS3_1.8.2 tools_4.3.2      
[37] withr_2.5.2   

接下来,我获取 C++ 代码:

Rcpp::sourceCpp("test.cpp")

给定

foo
一个列表,其
constraints
元素为
NULL
,按预期给出长度为零:

> data <- list(a = rnorm(100), constraints = NULL, b = letters)
> foo(data)
[1] 0

接下来,给它一个列表,其

constraints
元素有26个字母,返回长度26:

> data <- list(a = rnorm(100), constraints = letters, b = letters)
> foo(data)
[1] 26

在 Windows 上运行 R 的结果

我在 Windows 上运行相同的 R 代码,但得到不同的结果。

这是我的会话信息:

> sessionInfo()
R version 4.3.2 (2023-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19045)

Matrix products: default


locale:
[1] C

time zone: Europe/Oslo
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] compiler_4.3.2           magrittr_2.0.3           R6_2.5.1                
 [4] cli_3.6.1                tools_4.3.2              RcppArmadillo_0.12.6.6.0
 [7] rstudioapi_0.15.0        Rcpp_1.0.11.6            brio_1.1.3              
[10] testthat_3.2.0           rlang_1.1.2            

我再次获取脚本:

> Rcpp::sourceCpp("test.cpp")

这是当

constraints
NULL
时的结果。令人惊讶的是,它返回长度 1。

> data <- list(a = rnorm(100), constraints = NULL, b = letters)
> foo(data)
[1] 1

这是当

constraints
有26个字母时的结果。它再次返回长度 1。

> data <- list(a = rnorm(100), constraints = letters, b = letters)
> foo(data)
[1] 1

问题

这是预期的吗?我在这里做的事情是否会导致未定义的行为,从而在不同的编译器/平台上给出不同的结果?

我应该如何更改代码以获得我想要的行为,即当长度为

NULL
时长度应为零,否则为非零?

回答后更新

根据下面 Dirk Eddelbuettel 的回答,我意识到最好重构我的代码,使其不包含如此深的嵌套。无论如何,我认为值得在此提及的是,Eddelbuettel 的测试在 Windows 上返回的结果与在 Mac 上相同:

> Rcpp::cppFunction("int ll(List L) { return L.length(); }")
> ll(NULL)
[1] 0
> ll(letters)
[1] 26
c++ r rcpp
1个回答
1
投票

我无法访问Windows机器,但在我的Linux上,你的例子基本上似乎可以归结为

> Rcpp::cppFunction("int ll(List L) { return L.length(); }")
> ll(letters)
[1] 26
> ll(NULL)
[1] 0
> 

像您所做的那样嵌套多个结构,就像我们在 R 中所做的那样,并不总是可行或可取的,因为 C++ 代码需要一些微妙的模板元编程来展开结构。我一次又一次地发现,如果有疑问,首先尝试一些更简单的事情,然后从中积累会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.