从R调用C-在C执行期间分配的内存仅在重新启动R环境之后才释放

问题描述 投票:0回答:1

我正在使用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")))

enter image description here

r c memory allocation
1个回答
0
投票

我在这里看到问题:

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;
© www.soinside.com 2019 - 2024. All rights reserved.