Я пытаюсь запустить учебник по библиотеке libclang, но при вызове функции получаю нарушение прав доступа clang_getSpellingLocation()
, Другая информация об ошибке сообщается правильно с количеством ошибок, строкой и столбцом.
Моя среда: C ++ Builder XE pro, Windows 7 32bit, LLVM 3.4, libCLang.lib преобразован
используя coff2omf, libCLang.dll.
Я тестировал тот же код на Visual C ++ 2010, и он работает правильно.
Пожалуйста, кто-нибудь может мне помочь с этим вопросом?
Мой простой код
//---------------------------------------------------------------------------
void __fastcall TForm8::Button1Click(TObject *Sender)
{
unsigned line, column;
CXIndex index = clang_createIndex(0, 0);
const char * args [] = {
"-I/usr/include" ,
"-I."};
int numArgs = sizeof ( args ) / sizeof ( * args );
CXTranslationUnit tu = clang_parseTranslationUnit(index, "G:\\projects\\LibCLang \\File2.cpp", args, numArgs, NULL, 0, CXTranslationUnit_None);
unsigned diagnosticCount = clang_getNumDiagnostics ( tu );
for ( unsigned i = 0 ; i < diagnosticCount ; i++ )
{
CXDiagnostic diagnostic = clang_getDiagnostic ( tu , i );
CXSourceLocation location = clang_getDiagnosticLocation(diagnostic);
clang_getSpellingLocation(location, NULL, &line, &column, NULL);
CXString text = clang_getDiagnosticSpelling(diagnostic);
UnicodeString s = clang_getCString(text);
}
}
Вы уверены, что AV включен clang_getSpellingLocation()
и не clang_getDiagnosticSpelling()
?
При использовании __cdecl
Соглашение о вызовах, компиляторы от разных поставщиков могут делать все, что они хотят, когда дело доходит до возврата структуры по значению, когда размер структуры <= 8 байт. В случае clang_getDiagnosticSpelling()
, CXString
8 байтов в 32-битной среде. Некоторые компиляторы, такие как Visual C ++, возвращают содержимое 8-байтовой структуры непосредственно в EAX:EDX
Регистры ЦП, тогда как другие компиляторы, такие как C ++ Builder, используют скрытый выходной параметр, который передает ссылку на временную структуру.
clang_getDiagnosticSpelling()
(и другие подобные функции) возвращают CXString
с помощью EAX:EDX
, но C ++ Builder вместо этого использует скрытый параметр. Для этого есть простой обходной путь. C ++ Builder ожидает __cdecl
функция для возврата __int64
с помощью EAX:EDX
, и с тех пор CXString
а также __int64
одинакового размера в 32 бита, вы можете сделать следующее:
typedef __int64 __cdecl (*clang_getDiagnosticSpellingHack)(CXDiagnostic);
//CXString text = clang_getDiagnosticSpelling(diagnostic);
clang_getDiagnosticSpellingHack func = reinterpret_cast<clang_getDiagnosticSpellingHack>(&clang_getDiagnosticSpelling);
__int64 tmp = func(diagnostic);
CXString text = reinterpret_cast<CXString&>(tmp);
Кроме того, вы можете использовать C ++ Builder _EAX
а также _EDX
: встроенные функции
typedef void __cdecl (*clang_getDiagnosticSpellingHack)(CXDiagnostic);
//CXString text = clang_getDiagnosticSpelling(diagnostic);
clang_getDiagnosticSpellingHack func = reinterpret_cast<clang_getDiagnosticSpellingHack>(&clang_getDiagnosticSpelling);
CXString text;
func(diagnostic);
text.ptr_data = (void*) _EAX;
text.int_data = _EDX;
Что касается clang_getSpellingLocation()
Я бы не ожидал, что в соглашениях будет такое несоответствие, поскольку оно не имеет возвращаемого значения, если только clang_getSpellingLocation()
были скомпилированы, чтобы принять его CXSourceLocation
параметр отличается от того, как C ++ Builder передает его. C ++ Builder отправляет все три значения данных из CXSourceLocation
прямо на стек вызовов. Вам придется посмотреть на разборку clang_getSpellingLocation()
чтобы увидеть, как это на самом деле доступ к значениям его CXSourceLocation
параметра, а затем при необходимости скорректируйте код C ++ Builder соответствующим образом.
Вы должны также дважды проверить, как clang_getDiagnosticLocation()
возвращает свое CXSourceLocation
чтобы убедиться, что он соответствует тому, как C ++ Builder ожидает его возврата (через скрытый выходной параметр по ссылке), чтобы гарантировать, что память не будет повреждена до clang_getSpellingLocation()
называется Так что возможно, что clang_getSpellingLocation()
сам не может быть виновником. Трудно сказать, не видя разборки для обоих clang_getDiagnosticLocation()
а также clang_getSpellingLocation()
(Я видел разборку для функций, которые возвращают CXString
Вот так я точно знаю, что Clang использует EAX:EDX
для этого).
Других решений пока нет …