Hi all, Some time ago I reported an issue with using variable_watch in 3.4.1 on the user list (reproduced by David Cole using master at that time), see https://cmake.org/pipermail/cmake/2015-December/062213.html.
I finally found some time to get back to this and after some debugging I did find the cause of the problem. In short, what happens is that an internal memory reallocation inside an std::vector instance invalidates the char* that contained the actual value of the watched variable. It's not clear to me what would be the best fix though, hence this mail (and the lack of an attached patch ;)) It seems that for 3.4.1 I was "lucky" in that I was able to create a minimal test case to reproduce the problem. I cannot, however, reproduce the problem using the same test case with, e.g., current master, probably due to the unpredictable nature of std::vector reallocations, but when checking the CMake sources it seems that the problem itself is not fixed (but please, correct me if I'm wrong). Steps to reproduce: - CMake 3.4.1 - use the CMakeLists.txt from https://cmake.org/pipermail/cmake/2015-December/062213.html - Configure with VS2012 or VS2015 generator. This will fail and show strange symbols in the full path to FindPackageHandleStandardArgs.cmake that is being printed to stdout. The cause can be seen in cmMakefile: const char* cmMakefile::GetDefinition(const std::string& name) const { const char* def = this->StateSnapshot.GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); } #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); if ( vv && !this->SuppressWatches ) { if ( def ) { vv->VariableAccessed(name, cmVariableWatch::VARIABLE_READ_ACCESS, def, this); } else { vv->VariableAccessed(name, cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS, def, this); } } #endif return def; } What happens is that 'def' is assigned at the beginning of the function, but during the call to vv->VariableAccessed(...), there is an internal memory re-allocation inside one of the member variables inside the cmDefinitions class of type std::vector. This operation then invalidates the originally assigned 'def'. If I understand correctly, this reallocation is actually made possible in the first place by the const_cast in cmVariableWatchCommandVariableAccessed() in cmVariableWatchCommand.cxx. For this particular example (using VS2012 generator) the actual reallocation seems to be triggered by the call to cmMakefile::FunctionPushPop functionScope(...) in cmFunctionCommand::InvokeInitialPass. There are some possible solutions I see to fix the problem: 1. Avoid the const_cast? I'm not even sure it is possible in the current design... 2. Recompute 'def' after the call to VariableAccessed(). This seems cumbersome, maybe does not result in the desired behavior? 3. Define a move constructor in the cmDefinitions class. Probably that is not an option as IIRC CMake uses C++98. I did, however, check this solution locally, compiling CMake using VS2012 and can verify that it fixes the problem. Unfortunately, none of the above options seems optimal. If somebody with more knowledge about the CMake source would be willing to have a closer look at this, I can provide with any assistance that might be necessary. Also, I can provide a patch once the good solution is defined. Regards, Yves -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers