Вызов C из R - память, выделенная во время выполнения C, освобождается только после перезапуска среды R - PullRequest
0 голосов
/ 20 апреля 2020

Я разрабатываю пакет на R, который является гибридным и использует язык C для оптимизации скорости выполнения некоторых процессов.

Поскольку блок кода в языке C имеет много строк, я Я использую .Call, который отвечает за передачу некоторых параметров с языка R на язык C.

Недавно я понял, что для чтения небольших файлов нет проблем. Однако при чтении больших файлов, таких как файл примера (https://gofile.io/?c=PeQEOx) с двумя столбцами и более чем 80 тысячами строк, объем оперативной памяти (приблизительно 400 МБ) выделяется для выполнения .Call. Эта выделенная память нигде не найдена в 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

...