C функций в пакетах R - Rsession прервана после завершения функции - PullRequest
2 голосов
/ 04 февраля 2020

Проблема

Я пытаюсь обернуть старый код 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;
}

То, что я пробовал

Как я уже говорил, если я go ищу эффекты функции на ожидаемые системные файлы, я нахожу там все. Единственный способ предотвратить сбой Rsession - это выдать ошибку перед возвратом:

int main_(int* argc, char* argv[]){

  ... DO A LOT OF STUFF ...

  error("everything works up to this point");
  return 1;
}

Я пробовал много вещей совершенно слепо. Например, изменение int на void в определении функции и пропуск оператора return не помогает.

Я использовал 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

Хотя я не уверен, может ли это быть проблемой, этот побочный эффект обычно вызывается g_option_context_parse glib для анализа аргументов.

Подозрительно для меня, комментирование всего после строки g_option_context_parse все еще вызывает segfault, но комментирование этой строки и всего после того, как это не вызывает segfault.

Is R ожидает найти arg c и argv без изменений? Будет ли это sh, когда этого не произойдет?


К сожалению, это насколько я смог сделать самостоятельно.

Я пытался сохранить этот вопрос Короче, но полный источник C программы доступен (main определен в cell.c).

Буду признателен за вашу помощь. Дайте мне знать, как я могу улучшить свой вопрос, если это поможет.

1 Ответ

1 голос
/ 04 февраля 2020

Хакерское решение

Я обнаружил, что g_option_context_parse меняет argv таким образом, что при печати он показывает нулевые значения во всех позициях> 1:

cell (null) (null) (null) (null) (null) (null) (null) (null)

Это не в конфликт с документацией glib.

Но, если во время печати l oop в конце скрипта я назначаю ненулевое содержимое каждой позиции в массиве (то есть argv[i] = "";), Rsession больше не прерывается после завершения функции.

Несмотря на то, что это «заставляет его работать», я действительно не знаю, почему это происходит, и мое исправление гораздо более хакерское, чем то, с чем мне удобно.

Я приму ответы от кого-то сообразительного о том, как R и C взаимодействуют через .C, который может объяснить, почему это произошло, и как предотвратить это более элегантно.

...