stringstream在OSX 10.6上不与Rcpp一起使用

时间:2011-12-12 19:38:46

标签: c++ r osx-snow-leopard stringstream rcpp

似乎std :: stringstream不适用于Rcpp。为了解决这个问题,我写了一个最小的程序:

#include <string>
#include <sstream>
#include <Rcpp.h>

float atof(std::string a) {
        std::stringstream ss(a);
        Rf_PrintValue(Rcpp::wrap(a));
        float f;
        Rf_PrintValue(Rcpp::wrap(f));
        ss >> f;
        Rf_PrintValue(Rcpp::wrap(f));
        return (f);
}

RcppExport SEXP tsmall(SEXP sR) {
        std::string sC = Rcpp::as<std::string>(sR);
        return Rcpp::wrap(atof(sC));
}

tsmall应该只是将字符串转换为float。 Rf_PrintValue用于调试。现在在OSX 10.16.7上的R中,我得到了

> dyn.load("min.so")
> a = .Call("tsmall","0.213245")
[1] "0.213245"
[1] 0
[1] 0
> a
[1] 0

在另一台机器(Ubuntu)上,它按预期工作:

> dyn.load("min.so")
> a = .Call("tsmall","0.213245")
[1] "0.213245"
[1] 1.401298e-45
[1] 0.213245
> a
[1] 0.213245

我在OSX上尝试了一个小的普通C ++程序,当然可以使用stringstream来转换字符串和浮点数。

OSX上使用的编译器是MacPorts g ++ - mp-4.4。

更新 我在Stringstream not working with doubles when _GLIBCXX_DEBUG enabled找到了一个关于stringstream和OSX的问题。但是,当我使用/usr/bin/g++-4.2中的默认gcc-4.2编译该问题的测试程序时,我得到了错误,但使用/opt/local/bin/g++-mp-4.4进行编译工作正常。 / p>

但是,我已将Rcpp代码编译为

$ PKG_CPPFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'` \
         PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'` \
         R CMD SHLIB min.cpp

使用gcc-4.4:

/opt/local/bin/g++-mp-4.4 -I/opt/local/lib/R/include -I/opt/local/lib/R/include/x86_64 -I/opt/local/lib/R/library/Rcpp/include -I/opt/local/include    -fPIC  -pipe -O2 -m64 -c min.cpp -o min.o
/opt/local/bin/g++-mp-4.4 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/opt/local/lib -o min.so min.o /opt/local/lib/R/library/Rcpp/lib/x86_64/libRcpp.a -L/opt/local/lib/R/lib/x86_64 -lR

所以我不确定这是否是同一个问题。

更新2:https://discussions.apple.com/thread/2166586?threadID=2166586&tstart=0的讨论之后,我在代码的顶部添加了以下内容:

#ifdef GLIBCXXDEBUG
#define GLIBCXX_DEBUGDEFINED "1"
#else
#define GLIBCXX_DEBUGDEFINED "<undefined>"
#endif

并根据@ Kerrek的建议在f中将float f=0;初始化为stof(虽然这不会改变任何内容)。

Mac上的输出仍然相同。

2 个答案:

答案 0 :(得分:1)

我不知道R或RCPP,但我敢打赌以下代码会触发未定义的行为:

    float f;
    Rf_PrintValue(Rcpp::wrap(f));

在使用之前,您永远不会初始化 f,并且读取未初始化的变量是UB。说出像float f = 0;这样的东西是安全的。

答案 1 :(得分:1)

对于我来说,使用常规Xcode运行的编译器套件对我来说这很好。

> require(inline)
Le chargement a nécessité le package : inline
> require(Rcpp)
Le chargement a nécessité le package : Rcpp
Le chargement a nécessité le package : int64
> 
> inc <- '
+ float atof(std::string a) {
+         std::stringstream ss(a);
+         Rf_PrintValue(Rcpp::wrap(a));
+         float f = 0. ;
+         Rf_PrintValue(Rcpp::wrap(f));
+         ss >> f;
+         Rf_PrintValue(Rcpp::wrap(f));
+         return (f);
+ }
+ '
> 
> fx <- cxxfunction( signature( sR = "character" ), '
+     std::string sC = as<std::string>(sR);
+     return wrap(atof(sC));
+ ', plugin = "Rcpp", includes = inc )
> fx( "1.2" )
[1] "1.2"
[1] 0
[1] 1.2
[1] 1.2

您的R是否也使用gcc 4.4编译?