我正在使用R开发一个混合的程序包,该程序包使用C语言来优化某些进程的执行速度。
由于C语言中的代码块有很多行,因此我正在使用.Call,它负责将一些参数从R语言传递到C语言。
我最近意识到,读取小文件没有问题。但是,当读取较大的文件时,例如两行多于8万行的示例文件(https://gofile.io/?c=PeQEOx),将为执行.Call分配一定数量的RAM内存(大约400MB)。在R中找不到此分配的内存,只有在关闭程序或重新启动环境时才会释放该内存。这已经成为一个问题,因为有时我需要多次运行大型文件包。
我在几个站点和论坛中搜索了有关此问题的答案,但找不到解决方案。有没有人看到这个问题或知道解决方案? 我在Linux上创建了此测试,但我相信Windows上也会发生同样的问题。
输入文件示例:
Q0045 YJL166W
Q0045 YDL085W
Q0045 YDR119W-A
Q0045 YPR191W
Q0045 YNR018W
Q0045 Q0105
Q0045 YFR033C
Q0045 YML120C
Q0045 YEL024W
这是C中的代码:
#include <Rinternals.h>
#include <malloc.h>
int row_number;
SEXP asn;
char buffer[30];
const char ***read_file = NULL;
SEXP test(SEXP S_file) {
int len = length(S_file);
SEXP col1, col2;
col1 = VECTOR_ELT(S_file, 0);
col2 = VECTOR_ELT(S_file, 1);
row_number = length(col1);
read_file = (const char ***) malloc(sizeof(int *)*row_number);
for(int i=0; i<row_number; ++i){
*(read_file+i) = (const char **) malloc(sizeof(int)*row_number);
}
for (int i=0; i<row_number; i++) {
read_file[i][0] = CHAR(STRING_ELT(col1, i));
read_file[i][1] = CHAR(STRING_ELT(col2, i));
}
asn = PROTECT(Rf_allocMatrix(STRSXP,row_number, 2));
for (int i=0; i<row_number; i++) {
for (int n=0; n<2; n++) {
sprintf(buffer, "%s", read_file[i][n]);
SET_STRING_ELT(asn, i, Rf_mkChar(buffer));
}
}
free(read_file);
UNPROTECT(1);
return asn;
}
这是R中的代码:
file='/home/rafael/Documentos/yeast_08.txt'
file = data.frame(read.table(file, sep = "\t", stringsAsFactors = FALSE))
dyn.load(paste(find.package("example"),"libs", "example.so", sep = "/"))
R = suppressWarnings(suppressMessages(.Call("test",
S_file = file,
PACKAGE = "example")))
我在这里看到问题:
const char ***read_file = NULL;
...
read_file = (const char ***) malloc(sizeof(int *)*row_number);
for(int i=0; i<row_number; ++i){
*(read_file+i) = (const char **) malloc(sizeof(int)*row_number);
}
在第一个malloc
中,您想保留空间来存储指向指针的指针数组,但是要为指针数组保留空间。这不是什么大问题,因为可以肯定sizeof(int *) == sizeof(int**)
但是在malloc
循环中第二次调用for
时,出现了一个实际的问题:指向指针的指针(取消引用read_file
的结果)想要为指向int
的指针保留空间,不适用于您正在执行的int
数组。
const char ***read_file = NULL;
应该是
const char **read_file = NULL;