Есть ли способ заставить Rcpp перестать определять NDEBUG? - PullRequest
1 голос
/ 19 мая 2019

Почему здесь не работает assert?

^ По-видимому, Rcpp имеет привычку определять NDEBUG самостоятельно, даже если я не определен.

m@m-X555LJ:~/wtfdir$ cat WTF.r
#!/usr/bin/Rscript

library(Rcpp)

sourceCpp("WTF.cpp")
m@m-X555LJ:~/wtfdir$ cat WTF.cpp
#ifdef NDEBUG
#error WTF I did not define this
#endif
m@m-X555LJ:~/wtfdir$ ./WTF.r
WTF.cpp:2:2: error: #error WTF I did not define this
 #error WTF I did not define this
  ^~~~~
make: *** [WTF.o] Error 1
g++  -I"/usr/share/R/include" -DNDEBUG   -I"/home/m/R/x86_64-pc-linux-gnu-library/3.5/Rcpp/include" -I"/home/m/wtfdir"    -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-3U0YWo/r-base-3.5.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c WTF.cpp -o WTF.o
/usr/lib/R/etc/Makeconf:172: recipe for target 'WTF.o' failed
Error in sourceCpp("WTF.cpp") : Error 1 occurred building shared library.
Execution halted
m@m-X555LJ:~/wtfdir$ 

Ответы на вопрос SO, который я связал, чтобы объяснить, что (a) Запрещено вызывать assert в пакетах, загруженных в CRAN, потому что (b) код C ++ не должен останавливать код R и (c) я должен выбрасывать исключения вместо этого, которые перехвачены Rcpp.

Однако:

  • Я не хочу загружать свой код в CRAN; вместо этого я пишу код для собственного использования;
  • Даже если бы я захотел загрузить его в CRAN, я мог бы скомпилировать его самостоятельно без NDEBUG для целей тестирования, а затем определить NDEBUG непосредственно перед загрузкой в ​​CRAN;
  • Поскольку и R-код, и C ++-код написаны мной для одной и той же цели (и я считаю, что они обе - одна и та же программа), я бы на самом деле хотел, чтобы вся программа сработала, если в какой-либо ее части есть ошибка обнаружен; продолжать выполнение кода R, если код C ++ неисправен, для меня бессмысленно;
  • Поскольку я не знал, что NDEBUG будет определено, я уже поместил довольно много assert с в мой код, и печать диагностики через std::cerr обернута в #ifndef NDEBUG с; они не работают, очевидно;
  • Я не хочу безоговорочно генерировать исключения, поскольку некоторые assert s требуют большого объема вычислений;
  • На данный момент мой код C ++ все равно перегружает мой R-код, потому что он падает, я пытаюсь исследовать проблему, но не могу, потому что моя диагностика не работает.

Есть ли способ заставить Rcpp перестать определять NDEBUG? Или я должен просто удалить все asserts и все, что зависит от NDEBUG и переключиться на создание исключений и перестать жаловаться?

1 Ответ

4 голосов
/ 19 мая 2019

Прежде всего, если вы grep для NDEBUG в собственном R Makeconf (к которому мы можем получить доступ через удобную программную ссылку из /etc/R в Debian и его производных из-за того, как я установил пакет .deb):

edd@rob:~$ grep NDEBUG /etc/R/Makeconf 
R_XTRA_CPPFLAGS =  -I"$(R_INCLUDE_DIR)" -DNDEBUG
ALL_CPPFLAGS =  -I"$(R_INCLUDE_DIR)" -DNDEBUG $(PKG_CPPFLAGS) $(CLINK_CPPFLAGS) $(CPPFLAGS)
edd@rob:~$ 

вы видите, что на ваш вопрос наложено R , а не Rcpp.Так что ваше предположение было неверным.Он находится под вашим локальным управлением: просто отредактируйте R's Makeconf на вашем аппарате.Вы просто не можете автоматизировать это для гипотетических других пользователей вашего кода.Но, на ваш вопрос, это все равно не вызывает непосредственного беспокойства.

Во-вторых, если вам нужен конкретный #define, вы можете просто определить его:

Код

#include <Rcpp.h>

// [[Rcpp::export]]
void foo() {

#ifdef DEBUG
  Rcpp::Rcout << "foo: Debug mode" << std::endl;
#endif

  Rcpp::Rcout << "foo: Hello, world" << std::endl;
}

#define DEBUG 1

// [[Rcpp::export]]
void bar() {

#ifdef DEBUG
  Rcpp::Rcout << "bar: Debug mode" << std::endl;
#endif

  Rcpp::Rcout << "bar: Hello, world" << std::endl;
}


/*** R
foo()
bar()
*/

Вывод

R> sourceCpp("~/git/stackoverflow/56209693/answer.cpp")

R> foo()
foo: Hello, world

R> bar()
bar: Debug mode
bar: Hello, world
R> 

Довольно часто определяют другие макросы журналирования, такие как DEBUG или FATAL или ..., которые ведут себя как assert, даже если R по умолчанию (и по понятным причинам, какв первую очередь интерактивный инструмент) отключает assert.

Третий и последний, вы можете следовать подходу в этом вопросе и временно отменить определение NDEBUG, чтобы включить cassert, а затем переопределитьЭто.Это даст , даст вам assert() и завершит ваш сеанс, как я проверил.Не мой подход к отладке с R, но эй, если ты действительно должен ...

...