Нарушение доступа там, где его раньше не было - PullRequest
3 голосов
/ 30 января 2010

Я P / Invoking для Graphviz , как показано здесь . Когда я написал эту запись в блоге, код работал просто отлично. Теперь я собираю HttpModule, который отображает графики Graphviz с использованием этого кода, но я получаю AccessViolationException при agmemread.

// Native signature
Agraph_t agmemread(char *);

// P/Invoke Signature
[DllImport(LIB_GRAPH)]
private static extern IntPtr agmemread(string data);

// Usage
IntPtr g = agmemread(data);

Как я уже сказал, раньше это прекрасно работало. Но сейчас я не могу заставить свой код работать во всем. Даже мои старые приложения Graphviz, основанные на одном и том же коде, больше не работают.

Что я мог изменить, что могло бы вызвать это? Я даже не скачал новую версию Graphviz или что-то еще, поэтому библиотеки DLL все одинаковые.

РЕДАКТИРОВАТЬ: Я пытался изменить string на StringBuilder, но это дало тот же результат. Затем я добавил атрибут MarshalAs:

static extern IntPtr agmemread([MarshalAs(UnmanagedType.LPWStr)] string data);

После этого я больше не получаю AccessViolationException, но Graphviz не может правильно прочитать строку и возвращает нулевой указатель.

Ответы [ 2 ]

6 голосов
/ 30 января 2010

Неуправляемый код редко нуждается в большой помощи C #, чтобы начать генерировать нарушения прав доступа. Нет ничего плохого в вашей подписи P / Invoke, это не может быть причиной.

Наиболее распространенным источником AV в неуправляемом коде является повреждение кучи. Код C / C ++ не имеет сборщика мусора, память должна управляться явно. Он не только должен позаботиться об освобождении памяти (или утечке), он также отвечает за распределение правильного размера и следит за тем, чтобы код, записывающий в выделенную память, не записывал после конца выделенного блока памяти или пишет в память, которая уже была освобождена. Последнее требование - то, где код C / C ++ часто терпит неудачу.

Проблема с повреждением кучи заключается в том, что диагностировать крайне сложно. Это может остаться незамеченным в течение долгого времени. Типичный ущерб заключается в том, что внутренняя структура кучи скомпрометирована или данные в другом выделении кучи перезаписаны. Это не вызывает проблем до тех пор, пока не будет освобожден блок кучи или использованы перезаписанные данные. Код, который генерирует исключение, фактически не несет ответственности за ущерб, который был нанесен ранее. Это ставит вас на неверный путь, пытаясь найти источник проблемы.

Найти настоящего источника проблем очень сложно, у вас будет всего несколько хлебных крошек, чтобы выяснить, что могло пойти не так. Это очень трудно, когда у вас есть исходный код C / C ++, но помогает его запуск в отладочной сборке с помощью распределителя отладки. Это невозможно, если у вас нет исходного кода.

Если вы не можете точно определить проблему с использованием API из предыдущих вызовов, вам понадобится помощь поставщика или группы поддержки, чтобы действительно решить эту проблему. Удачи.

0 голосов
/ 26 сентября 2011

У меня была такая же проблема - для подписей P/Invoke требуется добавление CallingConvention=CallingConvention.Cdecl. Библиотеки Graphviz - это соглашение о вызовах C, а не StdCall.

См. эту тему .

...