需要使用C API通过Clang发布资源

Need to release resources with Clang using C API?

本文关键字:布资源 资源 Clang 通过 API      更新时间:2023-10-16

很抱歉有一个很傻的问题:当使用Clang C API函数时,我应该释放命令args-vars和未保存的文件结构吗?我知道在常见情况下应该释放资源以避免内存泄漏,但我想知道Clang是否在clang_disposeTranslationUnit()上自己这样做。

在parse/diags+tokenize/desole的几次迭代之后,我遇到了clang崩溃,所以我必须逐一消除可能的问题。

解析示例:

char **args;
CXUnsavedFile *files;
// allocate args
args = new char*[N];
for (int i=0; i<N; i++) {
  int len = strlen(argv[i]);
  args[i] = new char[len + 1];
  args[i][len] = 0;
  strcpy(arg[i], argv[i]);
}
// allocate unsaved files
files = new CXUnsavedFile[M];
for (int i=0; i<M; i++) {
  files[i].Filename = new char[BBB]; // + fill Filename
  files[i].Contents = new char[CCC]; // + fill Contents
  files[i].Length = strlen(files[i].Contents);
}
clang_parseTranslationUnit(..., args, N, files, M);
// release resources (need to do?)
// args
for (int i=0; i<N; i++) {
  delete []args[i];
}
delete[] args;
// unsaved files
for (int i=0; i<M; i++) {
  delete []files[i].Filename;
  delete []files[i].Contents;
}
delete []files;

最新消息:对于那些认为这真的很愚蠢的人来说,30秒内回答崩溃的原因是什么:

12-11 00:10:38.126: INFO/DEBUG(166): backtrace:
12-11 00:10:38.126: INFO/DEBUG(166): #00  pc 0001832a  /system/lib/libc.so
12-11 00:10:38.126: INFO/DEBUG(166): #01  pc 0000dc04  /system/lib/libc.so (abort+4)
12-11 00:10:38.126: INFO/DEBUG(166): #02  pc 0001f0df  /system/lib/libc.so (__assert2+30)
12-11 00:10:38.126: INFO/DEBUG(166): #03  pc 0077c954  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::Lexer::getSourceLocation(char const*, unsigned int) const+76)
12-11 00:10:38.126: INFO/DEBUG(166): #04  pc 0077ca4c  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::Lexer::FormTokenWithChars(clang::Token&, char const*, clang::tok::TokenKind)+100)
12-11 00:10:38.126: INFO/DEBUG(166): #05  pc 00781098  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::Lexer::LexTokenInternal(clang::Token&)+5616)
12-11 00:10:38.126: INFO/DEBUG(166): #06  pc 0015de68  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::Lexer::LexFromRawLexer(clang::Token&)+116)
12-11 00:10:38.126: INFO/DEBUG(166): #07  pc 00781d3c  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::Lexer::getRawToken(clang::SourceLocation, clang::Token&, clang::SourceManager const&, clang::LangOptions const&)+220)
12-11 00:10:38.126: INFO/DEBUG(166): #08  pc 00781d9c  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::Lexer::MeasureTokenLength(clang::SourceLocation, clang::SourceManager const&, clang::LangOptions const&)+36)
12-11 00:10:38.126: INFO/DEBUG(166): #09  pc 001d1824  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::DiagnosticRenderer::emitMacroExpansions(clang::SourceLocation, clang::DiagnosticsEngine::Level, llvm::ArrayRef<clang::CharSourceRange>, llvm::ArrayRef<clang::FixItHint>, clang::SourceManager const&, unsigned int&, unsigned int)+840)
12-11 00:10:38.126: INFO/DEBUG(166): #10  pc 001d13ec  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::DiagnosticRenderer::emitDiagnostic(clang::SourceLocation, clang::DiagnosticsEngine::Level, llvm::StringRef, llvm::ArrayRef<clang::CharSourceRange>, llvm::ArrayRef<clang::FixItHint>, clang::SourceManager const*, llvm::PointerUnion<clang::Diagnostic const*, clang::StoredDiagnostic const*>)+1224)
12-11 00:10:38.126: INFO/DEBUG(166): #11  pc 001d1b20  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::DiagnosticRenderer::emitStoredDiagnostic(clang::StoredDiagnostic&)+304)
12-11 00:10:38.126: INFO/DEBUG(166): #12  pc 0017b1c8  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang.so (clang::cxdiag::lazyCreateDiags(CXTranslationUnitImpl*, bool)+248)
12-11 00:10:38.126: INFO/DEBUG(166): #13  pc 00009028  /data/data/name.antonsmirnov.android.arduinodroid/lib/libclang_wrapper.so (Java_name_antonsmirnov_clang_clang_1wrapper_getDiagnostics+72)
12-11 00:10:38.126: INFO/DEBUG(166): #14  pc 0001fb70  /system/lib/libdvm.so (dvmPlatformInvoke+112)
12-11 00:10:38.126: INFO/DEBUG(166): #15  pc 0004e8b9  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+360)
12-11 00:10:38.126: INFO/DEBUG(166): #16  pc 00029020  /system/lib/libdvm.so
12-11 00:10:38.126: INFO/DEBUG(166): #17  pc 0002d7e8  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180)
12-11 00:10:38.126: INFO/DEBUG(166): #18  pc 0005fed5  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
12-11 00:10:38.126: INFO/DEBUG(166): #19  pc 0005feff  /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+20)
12-11 00:10:38.126: INFO/DEBUG(166): #20  pc 00055327  /system/lib/libdvm.so
12-11 00:10:38.126: INFO/DEBUG(166): #21  pc 00012e70  /system/lib/libc.so (__thread_entry+48)
12-11 00:10:38.126: INFO/DEBUG(166): #22  pc 000125c8  /system/lib/libc.so (pthread_create+172)

管理动态内存最可靠的方法是使用为此设计的类:

std::vector<char const *> args(argv, argv+N);  // replaces first loop
std::vector<CXUnsavedFile> files(M);
// Same loop to set up files
for (int i=0; i<M; i++) {
  files[i].Filename = "test_file.cpp";
  files[i].Contents = "int a = 10;";
  files[i].Length = strlen(files[i].Contents);
}
clang_parseTranslationUnit(..., args.data(), args.size(), files.data(), files.size());
// no need to delete anything.

如果你真的想通过为了教育目的而篡改指针来管理内存,那么我可以发现以下错误:

args = new char*[N];   // not '*args' - args doesn't point to anything yet
files = new CXUnsavedFile[M]  // not 'new CXUnsavedFile()' - you want an array

不要删除files[i].Filenamefiles[i].Contents,因为您没有new。它们指向具有静态生存期的字符串文字,这意味着它们在程序结束时会自动销毁。

是的,必须释放用new分配的资源。我崩溃是因为并发问题——同一文件的并发解析(clang_parseTranslationUnit)和索引(clang_indexSourceFile())。谢谢迈克。