gpt4 book ai didi

c - 注意带有 R 代码的 C 函数名称

转载 作者:太空狗 更新时间:2023-10-29 15:30:05 25 4
gpt4 key购买 nike

所以这里有点疯狂。

如果您有一些由 R 函数(作为共享对象)调用的 C 代码,请尝试将其添加到代码中

void warn() {

int i; // just so the function has some work, but you could make it empty to, or do other stuff

}

如果您随后在 R 函数调用的 C 代码中的任何位置调用 warn(),您将遇到段错误;

  *** caught segfault ***
address 0xa, cause 'memory not mapped'
Traceback:
1: .C("C_function_called_by_R", as.double(L), as.double(G), as.double(T), as.integer(nrow), as.integer(ncolL), as.integer(ncolG), as.integer(ncolT), as.integer(trios), as.integer(seed), as.double(pval), as.double(pval1), as.double(pval2), as.double(pval3), as.double(pval4), as.integer(ntest), as.integer(maxit), as.integer(threads), as.integer(quietly))
2: package_name::R_function(L, G, T, trios)
3: func()
4: system.time(func())
5: doTryCatch(return(expr), name, parentenv, handler)
6: tryCatchOne(expr, names, parentenv, handlers[[1L]])
7: tryCatchList(expr, classes, parentenv, handlers)
8: tryCatch(expr, error = function(e) { call <- conditionCall(e) if (!is.null(call)) { if (identical(call[[1L]], quote(doTryCatch))) call <- sys.call(-4L) dcall <- deparse(call)[1L] prefix <- paste("Error in", dcall, ": ") LONG <- 75L msg <- conditionMessage(e) sm <- strsplit(msg, "\n")[[1L]] w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], type = "w") if (is.na(w)) w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L], type = "b") if (w > LONG) prefix <- paste(prefix, "\n ", sep = "") } else prefix <- "Error : " msg <- paste(prefix, conditionMessage(e), "\n", sep = "") .Internal(seterrmessage(msg[1L])) if (!silent && identical(getOption("show.error.messages"), TRUE)) { cat(msg, file = stderr()) .Internal(printDeferredWarnings()) } invisible(structure(msg, class = "try-error", condition = e))})
9: try(system.time(func()))
10: .executeTestCase(funcName, envir = sandbox, setUpFunc = .setUp, tearDownFunc = .tearDown)
11: .sourceTestFile(testFile, testSuite$testFuncRegexp)
12: runTestSuite(testSuite)
aborting ...
Segmentation fault (core dumped)
(END)

不用说,如果您从 C 或 C++ 包装器而不是 R 函数调用相同的函数,代码运行良好。如果您重命名 warn(),它也可以正常工作。

有什么想法吗?这是 protected 名称/符号吗?是否有此类名称的列表?我在 Ubuntu 12.01(i686-pc-linux-gnu(32 位))上使用 R 版本 2.14.1。 C 代码使用 GNU GCC 4.6.3 编译。

最佳答案

这似乎是一个很有趣的问题。这是我的最小示例,在文件 test.c 我有

void warn() {}
void my_fun() { warn(); }

编译然后运行

$ R CMD SHLIB test.c
$ R -e "dyn.load('test.so'); .C('my_fun')"

在我的 linux gcc 版本 4.6.3 中,R 输出是

> dyn.load('test.so'); .C('my_fun')
R: Success
list()

“R: Success”来自 libc 中定义的 warn 函数(参见 man warn,在 err.h 中定义)。发生的事情是 R 理所当然地加载了几个动态库,然后按照指示加载 test.so。当调用 my_fun 时,动态链接器解析 warn,但解析规则是全局搜索 warn 符号,而不仅仅是在测试.so.我真的不知道全局搜索规则是什么,也许是按照打开 .so 的顺序,但无论如何,解决方案都不是我所期望的。

要做什么?指定

static void warn() {}

在创建 .o 时在编译时强制解析,从而避免了该问题。例如,如果 warn 定义在一个文件 (utilities.c) 中,而 my_fun 定义在另一个文件中,这将不起作用。在 Linux 上,dlopen(用于加载共享对象的函数)可以提供标志 RTLD_DEEPBIND,该标志在全局之前在本地进行符号解析,但是 (a) R 不使用dlopen 这样,(b) 有 several (见第9页)对这种做法持保留态度。因此,据我所知,最佳做法是尽可能使用 static,并仔细命名函数以避免名称冲突。后者并不像看起来那么糟糕,因为 R 加载包共享对象使得包符号本身不会添加到全局 namespace (参见 ?dyn.loadlocal 参数,还要注意特定于操作系统的警告)。

我有兴趣听到更强大的“最佳实践”。

关于c - 注意带有 R 代码的 C 函数名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11143023/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com