首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >有没有办法让Rcpp停止定义NDEBUG?

有没有办法让Rcpp停止定义NDEBUG?
EN

Stack Overflow用户
提问于 2019-05-20 00:16:32
回答 1查看 174关注 0票数 1

Why does assert not work here?

很明显,Rcpp有自己定义NDEBUG的习惯,即使不是我自己定义的。

代码语言:javascript
复制
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)禁止在上传到CRAN的包中调用assert,因为(b) C++代码不应该停止R代码,(c)我应该抛出异常,这是由Rcpp捕获的。

但是:

  • 我不希望将我的代码上传到CRAN;相反,我正在编写代码供我自己使用;
  • 即使我希望上传到CRAN,我也可以在没有NDEBUG的情况下自行编译它以用于测试目的,然后在上传到CRAN之前定义NDEBUG
  • 由于R代码和C++代码都是我自己为同一目的编写的(我认为它们是同一个程序),实际上我希望如果检测到程序中任何部分的错误,整个程序都会失效;如果C++代码有问题,继续运行R代码对我来说毫无意义;
  • 由于我不知道将定义NDEBUG,我已经在代码中放置了相当多的assert,并且通过std::cerr打印诊断也包装在#ifndef NDEBUGs中;这些显然无法工作;
  • 我不想无条件地抛出异常,因为有些assert计算繁重;< code >H221< code >H122到目前为止,我的C++代码无论如何都会损坏我的R代码,因为它崩溃了,我正在尝试调查这个问题,但我无法调查,因为我的诊断不起作用。< code >H223

有没有办法让Rcpp停止定义NDEBUG?或者我应该简单地删除所有asserts和任何其他依赖于NDEBUG的东西,并切换到抛出异常并停止抱怨?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-20 00:52:56

首先,如果您在R自己的Makeconf中为NDEBUG执行grep (由于我如何设置.deb包,我们可以通过/etc/R在Debian及其衍生产品上的一个方便的软链接访问它):

代码语言:javascript
复制
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的Makeconf即可。您不能为您的代码的假设其他用户自动执行此操作。但根据你的问题,这似乎不是一个直接的问题。

其次,如果你想要一个特定的#define,你可以直接定义它:

代码

代码语言:javascript
复制
#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()
*/

输出

代码语言:javascript
复制
R> sourceCpp("~/git/stackoverflow/56209693/answer.cpp")

R> foo()
foo: Hello, world

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

定义其他日志记录宏是很常见的,如DEBUGFATAL或...其行为类似于assert,即使在默认情况下R(出于主要交互式工具的原因)关闭了assert也是如此。

第三,也是最后一点,您可以遵循this question中的方法,暂时取消定义NDEBUG以包含cassert,然后重新定义它。这将给你assert()并终止你的会话,正如我检查的那样。不是我使用R进行调试的方法,但是如果你真的必须这样做的话...

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56209693

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档