Crash in ToLowercase()

I am using a VTK 9.0.1 that i just built.
I only try to run some examples for now. Exemples that only use vtkMath work with no issues.
But when trying some examples that do visual things, i end up getting a crash. With the first ‘Cylinder Example’ for example.

The end of the call stack is
-std::back_insert_iterator std::transform<__gnu_cxx::__normal_iterator<char const*, std::string>, std::back_insert_oterator>, int ()(int)>(__gnu_cxx::__normal_iterator<char const, std::string>, __gnu_cxx::__normal_iterator<char const*, std::string>, std::back_insert_iterator, int (*)(int))
-vtkNamedColorsDataStore::ToLowercase(vtkStdString const&)

The passed strings are simple, and the code of toLowercase() seems valid to me, so i don’t really understand what is hapenning.
Valgrind says “Invalid read of size 1” as last message

I hoped that it could be a bug in the STL of the first GCC i used (4.8), so i rebuilt VTK with GCC 9.3, but i am still getting the same issue.

I am not really sure what’s wrong at this point. Has anyone else seen this error?

OK, after some blind tests, i think what is hapenning is because of passing std::string by reference between user code and the library. VTK was built on machine A and the example on machine B with different build toolsets. Runing the example works on A with VTK built on A, and works on B with VTK built on B, but not if i mix A & B binaries.

While debugging, i can see that, when entering in vtkNamedColors::setColor(name, rgba), the debug value of name is only visible when not mixing libraries. And that’s also when the first valgrind warning is triggered in the non working configuration.

I knew passing std::string by reference between DLLs can fail like this on windows if the Dll and the executable are not built with the same visual C++ version. I didn’t know the problem could also be there on Linux

I can’t be the only one to have come up with this issue?

I’ve never seen this issue, but here are a couple tools that might help.

The “objdump” program can be used to find out what version of gcc was used to compile a file (can be used on executables, static libraries, dynamic libraries, and .o files):

objdump -s --section .comment vtkObject.cxx.o

vtkObject.cxx.o:     file format elf64-x86-64

Contents of section .comment:
 0000 00474343 3a202855 62756e74 7520392e  .GCC: (Ubuntu 9.
 0010 332e302d 31377562 756e7475 317e3230  3.0-17ubuntu1~20
 0020 2e303429 20392e33 2e3000             .04) 9.3.0.     

and the ldd command can be used to find out what libraries your program is dynamically linking to. With ldd and objdump, you might be able to discover discrepancies that point to the cause of the crash.

Edit: one thing to look for with ldd is whether your program is dynamically linked to libc++ instead of libstdc++. The latter is generally the default on linux.

When you say “different toolsets” between machines A & B, what do you mean? Different versions of GCC?

vtkNamedColors::SetColor() takes a vtkStdString parameter. Presumably building VTK with a different compiler means vtkStdString on machine A is a different object type from that on machine B.

I think only const char* should ever appear in VTK’s public API for methods containing text parameters.

One machine is centos6 with gcc 4.8/GLIBC 2.12. Another is centos7 with gcc 9.3/GLIBC 2.17. Another is Ubuntu18 with gcc7.5/glibc 2.27. I did not look what libstdc++ versions they use yet.

An example debugged on the ubuntu runs with a VTK built on that ubuntu. but not a VTK built on the CENTOS machines.
I also tested on the centos7 machine, which can run examples with a VTK built on this machine, but the VTK built on the ubuntu machine does a SEGV (same error location)

std::string, behind vtkStdString, being a template type, the template code of std::string that gets integrated in the library is the one of the compiler used to build the library (visible with the source path when debugging inside std::transform caled by Tolowercase()).
I don’t know to what extent g++ headers try to keep template types binary compatible between versions, but i know problems can occur on windows with different Visual C++. A public API of something i work on, that used std::string, has had to be changed so that the type string that is exchanged between the library & user code is a char*, or an abstract string type whose implementation is in the library only.

For my personal situation, i think i will just build a VTK for each build toolset i want to use.

That’s the correct approach.

That’s actually your only option. COM was designed to permit passing objects (interfaces actually) across library boundaries. Doing it in C++ is nothing but a hack in my opinion.

Using text as a key in the colour map is another problem. It should be an enumeration or integer key mapped to names.