【发布时间】:2020-05-19 16:57:44
【问题描述】:
问题
我正在尝试将旧的 C 代码包装到 R 包中。
到目前为止,我已经设法让 RStudio 编译代码、导出函数,并且函数主体中的所有内容都可以正确执行,直到执行结束。
然后,Rsession 中止并且没有错误消息(除了重启会话按钮)。
我的问题是:为什么?以及如何解决?
编辑:我找到了一种让它工作的方法,它在这篇文章的结尾,但我仍然没有回答这两个问题。
代码位
包装器看起来像这样:
#' @useDynLib mypackage main_
#' @export
cellid <- function(args) {
# Example input:
# args <- "cell -p ~/Projects/Colman/HD/scripts/cellMagick/data/images/parameters.txt -b /tmp/Rtmp7fjlFo/file2b401093d715 -f /tmp/Rtmp7fjlFo/file2b402742f6ef -o ~/Projects/Colman/HD/uscope/20200130_screen_act1_yfp/1/Position001/out"
argv <- strsplit(args, " ")[[1]] # Split arguments
argc <- length(argv) # Get length
.C(main_, as.integer(argc), as.character(argv))
}
实际功能如下:
int main_(int* aargc, char* argv[]){
... DO A LOT OF STUFF ...
return 1;
}
我尝试过的
正如我之前所说,如果我去寻找函数对预期系统文件的影响,我会在那里找到所有内容。我必须防止 Rsession 崩溃的唯一方法是在返回之前引发错误:
int main_(int* argc, char* argv[]){
... DO A LOT OF STUFF ...
error("everything works up to this point");
return 1;
}
我尝试了很多东西,很盲目。例如,在函数定义中将 int 更改为 void 并省略 return 语句并没有帮助。
我按照here 的建议使用了 lldb,从中得到以下信息:
Process 7900 stopped
* thread #1, name = 'R', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
frame #0: 0x00007ffff7a946f5 libc.so.6`__strlen_avx2 + 21
libc.so.6`__strlen_avx2:
-> 0x7ffff7a946f5 <+21>: vpcmpeqb (%rdi), %ymm0, %ymm1
0x7ffff7a946f9 <+25>: vpmovmskb %ymm1, %eax
0x7ffff7a946fd <+29>: testl %eax, %eax
0x7ffff7a946ff <+31>: jne 0x7ffff7a947f0 ; <+272>
我无法解释,我的 C 技能基本为零。
缩小原因
我只能将问题缩小到 C 函数结束的那部分,而 R 必须继续(我猜)。
也许问题出在指针对象上(argv 和argc)。我注意到argc 和argv 在函数执行过程中改变了它们的内容(即它们被缩短了,见下文)。
函数开头:
Input argument number (argc[0]): 9
Input argument (argv[i] for printf): cell -p ~/Projects/Colman/HD/scripts/cellMagick/data/images/parameters.txt -b /tmp/Rtmplr4Q90/file26f12a94a144 -f /tmp/Rtmplr4Q90/file26f175cd02e5 -o ~/Projects/Colman/HD/uscope/20200130_screen_act1_yfp/1/Position001/out
函数结束时:
Input argument number (argc[0]): 1
Input argument (argv[i] for printf): cell
虽然我不确定这是否会成为问题,但这种副作用通常是由 glib 的 g_option_context_parse 解析参数引起的。
对我来说很可疑,在 g_option_context_parse 行之后评论所有内容仍然会导致段错误,但评论该行 和之后的所有内容不会导致段错误。
R 是否期望发现 argc 和 argv 不变?如果没有,它会崩溃吗?
不幸的是,这是我自己能够做到的。
我试图让这个问题保持简短,但完整的source of the C program 是可用的(main 定义在cell.c)。
感谢您的帮助。如果有帮助,请告诉我如何改进我的问题。
【问题讨论】:
-
表示您将 NULL 或未对齐的指针传递给
strlen。检查堆栈是否为 16 字节对齐。 -
啊,是的。那是你的问题。
vpcmpeqb(一个 x86 指令)可能要求参数是 16 字节对齐的,并且由于您的堆栈未对齐,它可能不起作用。 -
不幸的是,我相当于我研究所的 IT 部门。
-
你应该把你的解决方案放在答案而不是评论中。另外,
argc应该是参数,而不是数组,argv[argc]应该是NULL。