Исключение StackOverflow в неуправляемой Dll при вызове из управляемой DLL - PullRequest
2 голосов
/ 24 марта 2010

Мой вопрос похож на здесь , но есть некоторая разница.

У меня есть fortran dll в качестве бэкэнда и C # exe в качестве внешнего интерфейса. Я использую PInvoke для передачи данных между ними.

Между C # и кодом Фортрана 22 параметра. И некоторые из них целочисленные, двойные, указатели (указатели C #), массив и еще много чего. Так что это сочетание типов.

Проблема в том, что для небольших массивов код работает нормально, однако для больших массивов (размер элемента ~ 10k) исключение stackoverflow было вызвано сразу после того, как мой код входит в управляемый код.

Редактировать: мне удалось все уменьшить. Вот код Фортрана:

  subroutine chartest(maxncv,ldv)

  !DEC$ ATTRIBUTES DLLEXPORT::chartest
  !DEC$ ATTRIBUTES ALIAS:'chartest'::chartest
   !DEC$ ATTRIBUTES VALUE :: maxncv,ldv

 &    

   integer, intent(in)  :: maxncv, ldv

  Double precision
 &                  v(ldv,maxncv),d(maxncv,2)

   print *, 'hello'

  end

А вот мое объявление на C #:

    public static extern void chartest(

       [MarshalAs(UnmanagedType.I4)] int maxncv,
          [MarshalAs(UnmanagedType.I4)] int ldv


   );

Если я позвоню chartest(546, 547), я получу исключение stackoverflow.

546*547=298662, это не похоже на большое количество элементов, нет?

Ответы [ 2 ]

2 голосов
/ 25 марта 2010

Вы не упоминаете, с чем вы компилируете свой Фортран, но очевидно, что когда вы выделяете массив, эта память выделяется в стеке, что очень плохо. .NET предполагает, что большая часть содержимого стека будет небольшой, например ссылки на объекты или целые числа, поэтому по умолчанию используется размер стека 1 МБ.

Ваш пример 298662 удвоений (каждый из которых, вероятно, составляет 8 или 10 байт) находится в области 2-3 МБ, что превышает размер стека в 1 МБ.

Я нашел ссылку на опцию для компилятора Intel Fortran:

http://software.intel.com/en-us/forums/showthread.php?t=53881

В нем говорится, что вы можете избежать размещения массивов в стеке, передавая / heap-массивы компилятору. Я хотел бы надеяться, что другие компиляторы Фортрана будут иметь что-то похожее, или использовать массивы кучи по умолчанию.

1 голос
/ 24 марта 2010

Я довольно озадачен этим, но некоторые поиски в Google, кажется, указывают, что невозможно «легко» изменить размер стека в управляемом приложении. Возможно, мое отсутствие знаний мешает мне понять, почему это не важно. Но кажется, что вы можете увеличить размер стека с помощью утилиты editbin.exe, если она вызывается из вашего основного потока. Если вы делаете вызов в отдельном созданном вами потоке, вы можете указать размер стека. Это сообщение в блоге говорит об этом.

...