stringstream не работает с Rcpp в OSX 10.6

Кажется, что 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 должен просто преобразовать строку в число с плавающей запятой. Rf_PrintValue предназначен для отладки. Теперь в R на OSX 10.16.7 я получаю

> 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

Я попробовал небольшую обычную программу C ++ на OSX, и, конечно же, она отлично работает при использовании строкового потока для преобразования строк и чисел с плавающей запятой.

В OSX используется компилятор MacPorts g ++ - mp-4.4.

Обновление: я обнаружил проблему, поднятую ранее о строковом потоке и OSX в Stringstream, не работающем с двойными значениями при включенном _GLIBCXX_DEBUG . Однако, когда я компилирую тестовую программу в этой проблеме с gcc-4.2 по умолчанию в /usr/bin/g++-4.2, я получаю сообщение об ошибке, но компиляция с /opt/local/bin/g++-mp-4.4 работает нормально.

Однако я скомпилировал код 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

а также инициализировал f как float f=0; в stof в соответствии с предложением @Kerrek (хотя это ничего не должно изменить).

Вывод на Mac все тот же.


person highBandWidth    schedule 12.12.2011    source источник


Ответы (2)


Я не знаю R или RCPP, но держу пари, что следующий код вызывает неопределенное поведение:

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

Вы никогда не инициализируете f его перед использованием, а чтение неинициализированной переменной - это UB. На всякий случай скажите что-нибудь вроде float f = 0;.

person Kerrek SB    schedule 12.12.2011
comment
Я сделал это, чтобы увидеть, откуда взялось возвращаемое значение. Я могу изменить его на инициализированное значение с плавающей запятой как float f=0;, и результат останется прежним. - person highBandWidth; 12.12.2011

Это прекрасно работает для меня на Lion с обычным комплектом компиляторов 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?

person Romain Francois    schedule 14.12.2011
comment
Спасибо! Этот код также просто возвращает 0. Я не уверен в компиляции R. Я просто установил его с помощью MacPorts, и я не уверен, использовал ли Macports XCode gcc или установленный gcc. Я мог бы создать еще один R и протестировать его в любом случае, если он поможет. Хотя я думаю, что возможная проблема, о которой я упоминал в 10.6, была исправлена ​​в 10.7 (Lion), поэтому она может не отображаться в вашей системе. - person highBandWidth; 14.12.2011
comment
Я загрузил готовый стабильный двоичный файл с cran.r-project.org/bin/macosx И с этим все нормально работало. Проблема, я думаю, только в Macports R, потому что он, вероятно, использует плохой gcc 10.6. - person highBandWidth; 16.12.2011
comment
возможно. обычно я стараюсь избежать неприятностей, просто используя компиляторы и т. д., поставляемые XCode. - person Romain Francois; 16.12.2011