有没有办法让 Rcpp 停止定义 NDEBUG?
Is there any way to make Rcpp stop defining NDEBUG?
Why does assert not work here?
^ 显然,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) 禁止在上传到 CRAN 的包中调用 assert
,因为 (b) C++ 代码不应停止 R 代码,并且 (c)我应该抛出异常,由 Rcpp 捕获。
但是:
- 我不想将我的代码上传到 CRAN;相反,我正在编写自己使用的代码;
- 即使我想将它上传到 CRAN,我也可以在没有
NDEBUG
的情况下自己编译它以进行测试,然后在上传到 CRAN 之前定义 NDEBUG
;
- 因为R代码和C++代码都是我自己为了同一个目的而写的(而且我认为它们是同一个程序),如果任何部分出现错误,我实际上希望整个程序崩溃它被检测到;如果 C++ 代码有问题,继续 运行 R 代码对我来说毫无意义;
- 因为我不知道
NDEBUG
会被定义,所以我已经在我的代码中放置了很多 assert
并且通过 std::cerr
打印诊断信息也包含在 #ifndef NDEBUG
秒;这些显然不起作用;
- 我不想无条件抛出异常,因为有些
assert
计算量很大;
- 截至目前,我的 C++ 代码无论如何都会破坏我的 R 代码,因为它崩溃了,我正在尝试调查这个问题,但我不能,因为我的诊断不起作用。
有没有办法让 Rcpp 停止定义 NDEBUG
?或者我应该简单地删除所有 asserts
和任何依赖于 NDEBUG
的东西并切换到抛出异常并停止抱怨?
首先,如果您在 R 自己的 Makeconf
中 grep
for NDEBUG
(我们可以通过来自 /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 的 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/Whosebug/56209693/answer.cpp")
R> foo()
foo: Hello, world
R> bar()
bar: Debug mode
bar: Hello, world
R>
定义其他日志记录宏如 DEBUG
或 FATAL
或 ... 是很常见的] 工具)关闭 assert
。
第三个也是最后一个,您可以按照this question中的方法暂时取消定义NDEBUG
以包含cassert
,然后重新定义它。 将 给你 assert()
并终止你的会话,正如我检查的那样。不是我使用 R 进行调试的方法,但嘿,如果你真的必须...
Why does assert not work here?
^ 显然,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) 禁止在上传到 CRAN 的包中调用 assert
,因为 (b) C++ 代码不应停止 R 代码,并且 (c)我应该抛出异常,由 Rcpp 捕获。
但是:
- 我不想将我的代码上传到 CRAN;相反,我正在编写自己使用的代码;
- 即使我想将它上传到 CRAN,我也可以在没有
NDEBUG
的情况下自己编译它以进行测试,然后在上传到 CRAN 之前定义NDEBUG
; - 因为R代码和C++代码都是我自己为了同一个目的而写的(而且我认为它们是同一个程序),如果任何部分出现错误,我实际上希望整个程序崩溃它被检测到;如果 C++ 代码有问题,继续 运行 R 代码对我来说毫无意义;
- 因为我不知道
NDEBUG
会被定义,所以我已经在我的代码中放置了很多assert
并且通过std::cerr
打印诊断信息也包含在#ifndef NDEBUG
秒;这些显然不起作用; - 我不想无条件抛出异常,因为有些
assert
计算量很大; - 截至目前,我的 C++ 代码无论如何都会破坏我的 R 代码,因为它崩溃了,我正在尝试调查这个问题,但我不能,因为我的诊断不起作用。
有没有办法让 Rcpp 停止定义 NDEBUG
?或者我应该简单地删除所有 asserts
和任何依赖于 NDEBUG
的东西并切换到抛出异常并停止抱怨?
首先,如果您在 R 自己的 Makeconf
中 grep
for NDEBUG
(我们可以通过来自 /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 的 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/Whosebug/56209693/answer.cpp")
R> foo()
foo: Hello, world
R> bar()
bar: Debug mode
bar: Hello, world
R>
定义其他日志记录宏如 DEBUG
或 FATAL
或 ... 是很常见的] 工具)关闭 assert
。
第三个也是最后一个,您可以按照this question中的方法暂时取消定义NDEBUG
以包含cassert
,然后重新定义它。 将 给你 assert()
并终止你的会话,正如我检查的那样。不是我使用 R 进行调试的方法,但嘿,如果你真的必须...