Closed xinbada007 closed 1 year ago
@xinbada007
If possible, please try to checkout latest master
from clang-uml
(I've fixed 2 known segfaults since 0.3.5), build it in debug mode:
git clone https://github.com/bkryza/clang-uml.git
cd clang-uml
make debug
export CLANG_UML_PATH=$PWD
cd <your project folder>
$CLANG_UML_PATH/debug/src/clang-uml -vvv -n your_class_diagram_name
Now if it crashes again, you should get stack trace in the terminal, please share it here along with your configuration file...
If you can't build it on your system, please at least rerun clang-uml
using:
clang-uml -vvv -n your_class_diagram_name
and paste the end of the output from the terminal before crash and also your .clang-uml
configuration file...
Stack trace (most recent call last) in thread 1072727:
297: static void
298: _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
299: {
> 300: (*_Base::_M_get_pointer(__functor))(
301: std::forward<_ArgTypes>(__args)...);
302: }
303: };
170: db = std::ref(*db), translation_units = valid_translation_units,
171: verbose]() {
172: try {
> 173: generate_diagram(od, name, diagram, db, translation_units,
174: generators, verbose != 0);
175: }
176: catch (std::runtime_error &e) {
121: using clanguml::config::sequence_diagram;
122:
123: if (diagram->type() == diagram_t::kClass) {
> 124: detail::generate_diagram_impl<class_diagram>(
125: od, name, diagram, db, translation_units, generators, verbose);
126: }
127: else if (diagram->type() == diagram_t::kSequence) {
88: using diagram_model = typename diagram_model_t<DiagramConfig>::type;
89: using diagram_visitor = typename diagram_visitor_t<DiagramConfig>::type;
90:
> 91: auto model = clanguml::common::generators::generate<diagram_model,
92: diagram_config, diagram_visitor>(db, diagram->name,
93: dynamic_cast<diagram_config &>(*diagram), translation_units, verbose);
245: std::make_unique<diagram_action_visitor_factory<DiagramModel,
246: DiagramConfig, DiagramVisitor>>(*diagram, config);
247:
> 248: auto res = clang_tool.run(action_factory.get());
249:
250: if (res != 0) {
251: throw std::runtime_error("Diagram " + name + " generation failed");
154: void HandleTranslationUnit(clang::ASTContext &ast_context) override
155: {
> 156: visitor_.TraverseDecl(ast_context.getTranslationUnitDecl());
157: visitor_.finalize();
158: }
159: };
598: #ifndef TRANSLATIONUNIT
599: # define TRANSLATIONUNIT(Type, Base) DECL(Type, Base)
600: #endif
> 601: TRANSLATIONUNIT(TranslationUnit, Decl)
602: #undef TRANSLATIONUNIT
603:
604: LAST_DECL_RANGE(Decl, AccessSpec, TranslationUnit)
1487: TRY_TO(TraverseStmt(D->getMessage()));
1488: })
1489:
>1490: DEF_TRAVERSE_DECL(
1491: TranslationUnitDecl,
1492: {// Code in an unnamed namespace shows up automatically in
1493: // decls_begin()/decls_end(). Thus we don't need to recurse on
1387: for (auto *Child : DC->decls()) {
1388: if (!canIgnoreChildDeclWhileTraversingDeclContext(Child))
>1389: TRY_TO(TraverseDecl(Child));
1390: }
1391:
1392: return true;
108: #ifndef NAMESPACE
109: # define NAMESPACE(Type, Base) NAMED(Type, Base)
110: #endif
> 111: NAMESPACE(Namespace, NamedDecl)
112: #undef NAMESPACE
113:
114: #ifndef NAMESPACEALIAS
1511: DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl.
1512: })
1513:
>1514: DEF_TRAVERSE_DECL(
1515: NamespaceDecl,
1516: {// Code in an unnamed namespace shows up automatically in
1517: // decls_begin()/decls_end(). Thus we don't need to recurse on
1387: for (auto *Child : DC->decls()) {
1388: if (!canIgnoreChildDeclWhileTraversingDeclContext(Child))
>1389: TRY_TO(TraverseDecl(Child));
1390: }
1391:
1392: return true;
108: #ifndef NAMESPACE
109: # define NAMESPACE(Type, Base) NAMED(Type, Base)
110: #endif
> 111: NAMESPACE(Namespace, NamedDecl)
112: #undef NAMESPACE
113:
114: #ifndef NAMESPACEALIAS
1511: DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl.
1512: })
1513:
>1514: DEF_TRAVERSE_DECL(
1515: NamespaceDecl,
1516: {// Code in an unnamed namespace shows up automatically in
1517: // decls_begin()/decls_end(). Thus we don't need to recurse on
1387: for (auto *Child : DC->decls()) {
1388: if (!canIgnoreChildDeclWhileTraversingDeclContext(Child))
>1389: TRY_TO(TraverseDecl(Child));
1390: }
1391:
1392: return true;
216: #ifndef TYPEALIASTEMPLATE
217: # define TYPEALIASTEMPLATE(Type, Base) REDECLARABLETEMPLATE(Type, Base)
218: #endif
> 219: TYPEALIASTEMPLATE(TypeAliasTemplate, RedeclarableTemplateDecl)
220: #undef TYPEALIASTEMPLATE
221:
222: #ifndef VARTEMPLATE
1812: // source.
1813: })
1814:
>1815: DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, {
1816: TRY_TO(TraverseDecl(D->getTemplatedDecl()));
1817: TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
1818: })
216: #ifndef TYPEALIASTEMPLATE
217: # define TYPEALIASTEMPLATE(Type, Base) REDECLARABLETEMPLATE(Type, Base)
218: #endif
> 219: TYPEALIASTEMPLATE(TypeAliasTemplate, RedeclarableTemplateDecl)
220: #undef TYPEALIASTEMPLATE
221:
222: #ifndef VARTEMPLATE
257: return true;
258:
259: auto template_specialization_ptr =
> 260: tbuilder().build(cls, *template_type_specialization_ptr);
261:
262: if (!template_specialization_ptr)
263: return true;
206: base_index++;
207: }
208:
> 209: process_template_arguments(parent, cls, template_base_params,
210: template_type.template_arguments(), template_instantiation,
211: template_decl);
397: //
398: // Handle the template parameter/argument based on its kind
399: //
> 400: argument_process_dispatch(parent, cls, template_instantiation,
401: template_decl, arg, arg_index, arguments);
402:
403: if (arguments.empty()) {
450: argument.push_back(process_null_argument(arg));
451: break;
452: case clang::TemplateArgument::Template:
> 453: argument.push_back(process_template_argument(arg));
454: break;
455: case clang::TemplateArgument::Type: {
456: argument.push_back(process_type_argument(parent, cls, template_decl,
487: LOG_DBG("Processing template argument: {}", common::to_string(arg));
488:
489: auto arg_name =
> 490: arg.getAsTemplate().getAsTemplateDecl()->getQualifiedNameAsString();
491:
492: return template_parameter::make_template_type(arg_name);
493: }
Segmentation fault (Address not mapped to object [0x1c]) Segmentation fault (core dumped)
@xinbada007 Thank you for the details - I've patched this bug in master.
One more thing, in your config file you are using wildcards in your namespace filters, which are not yet supported, please change your include
filters to:
include:
namespace:
- project::namespace
context:
- project::namespace::class
and remove your exclude
filter - if you provide an include
namespace filter, it will only include entities from this namespace, you don't need to exclude any other namespaces unless they are sub namespaces of project::namespace
.
Please try again, and if it still crashes please paste the stack trace...
@xinbada007 Also, since you mentioned this is a large code base, try to use the glob
pattern to limit the number of source files that are visited for each diagram. In particular, if you're generating a context of a specific class, usually you only need to add the source file for this class, as all headers necessary to generate the context will be traversed anyway through #include
directives, i.e.:
glob:
- src/my_class.cpp
This will significantly decrease the generation times...
@bkryza oh man it's working! I got a large puml(class diagram) like 150KB~ (only used a single .cc as you suggested). Now I got trouble viewing it. it's too slow to view in vs-code with plantuml. I tried with official plantuml.jar and it can't even print the graph right (only a small part of the whole picture compared to that in vs-code with plantuml).
I would appreciate any suggestions regarding visualization tools (especially for large uml).
@xinbada007 Glad it's working.
First of all, try to limit the amount of classes you have in one diagram using the include/exclude filters. Actually the context
diagram should ensure that the diagram only contains elements in direct relationship to mentioned class, but there still can be a lot of them...
Second of all, if you have a lot of dependency
relationships but you don't need them, you can remove them from the diagram using:
exclude:
relationships:
- dependency
Next, you can also remove private and protected members and methods from the class descriptions using:
exclude:
access:
- protected
- private
If you really need such large diagrams, then do not generate PNG but SVG instead:
plantuml -tsvg docs/diagrams/localview.puml
This will ensure that the entire diagram is rendered.
You can then view it using your web browser or most generic image viewers on Linux such as gwenview
.
Hi,
I am trying to generate diagrams for a project containing tens of thousands lines of codes. The codes are also compiled with many third-party like protobuf, boost, eigen, sqlite, ...
The project is also compiled using CMake + Clang under ubuntu 20.04, so complie_commands.json is provided.
Clang-UML 0.3.5 is installed and yaml is configed. During runing, clang-uml first prompted a few info showing compilation process and a few warnings, then it core dumped. Tried every diagram, only package diagram for a specified subfolder of the project got lucky.