[CMake] Memory cleanup of variables

Bill Hoffman bill.hoffman at kitware.com
Wed Mar 11 07:58:47 EDT 2009


Naram Qashat wrote:
> Bill Hoffman wrote:
>> Naram Qashat wrote:
>>> I have a CMake project that I have been testing with various verisons 
>>> of CMake 2.4.x and 2.6.x to make sure it works as far back as 2.4.0, 
>>> due to not knowing what version of CMake our users will be using 
>>> since a lot of them use shells. In some instances, I have to read 
>>> lines from a file using a specific regular expression.  With CMake 
>>> 2.6.x, this works fine using the file(STRINGS) command.  With CMake 
>>> 2.4.x, though (I haven't checked what versions specifically), after 
>>> reading in a lot of files, I notice that a "memory exhausted" error 
>>> comes up. I'm wondering when CMake cleans up the memory it uses, and 
>>> if there is a way around this problem.  I would prefer not to force 
>>> our uses to use CMake 2.6.x if their shell provider won't provide 
>>> them something newer.
>>>
>> There may have been leaks in 2.4.X, not really much we can do about 
>> that now....   What does the your cmake code look like that causes the 
>> leak?
>>
>>
>> -Bill
> 
> I believe it is within this macro of mine:
> 
> macro(read_from_file FILE REGEX STRINGS)
>   if(CMAKE26_OR_BETTER)
>     # For CMake 2.6.x or better, we can just use the STRINGS sub-command 
> to get the lines that match the given regular expression (if one is 
> given, otherwise get all lines)
>     if(REGEX STREQUAL "")
>       file(STRINGS ${FILE} RESULT)
>     else(REGEX STREQUAL "")
>       file(STRINGS ${FILE} RESULT REGEX ${REGEX})
>     endif(REGEX STREQUAL "")
>   else(CMAKE26_OR_BETTER)
>     # For CMake 2.4.x, we need to do this manually, firstly we read the 
> file in
>     file(READ ${FILE} ALL_STRINGS)
>     # Next we replace all newlines with semicolons
>     string(REGEX REPLACE "\n" ";" ALL_STRINGS ${ALL_STRINGS})
>     if(REGEX STREQUAL "")
>       # For no regular expression, just set the result to all the lines
>       set(RESULT ${ALL_STRINGS})
>     else(REGEX STREQUAL "")
>       # Clear the result list
>       set(RESULT)
>       # Iterate through all the lines of the file
>       foreach(STRING ${ALL_STRINGS})
>         # Check for a match against the given regular expression
>         string(REGEX MATCH ${REGEX} STRING_MATCH ${STRING})
>         # If we had a match, append the match to the list
>         if(STRING_MATCH)
>           append_to_list(RESULT ${STRING})
>         endif(STRING_MATCH)
>       endforeach(STRING)
>     endif(REGEX STREQUAL "")
>   endif(CMAKE26_OR_BETTER)
>   # Set the given STRINGS variable to the result
>   set(${STRINGS} ${RESULT})
> endmacro(read_from_file)
> 
> I had done this so I could call the macro and have it work with either 
> 2.6.x or 2.4.x.
> 
The only thing I can think of is to call a new cmake process in the loop 
that does the string match, that way the leak will be contained in that 
process.

execute_process(COMMAND ${CMAKE_COMMAND} -DFILE="${FILE}"-P 
myscript.cmake OUTPUT_VARIABLE OUT)

myscript.cmake
  file(READ ${FILE} ALL_STRINGS)
...
   message(${RESULT})

-Bill


More information about the CMake mailing list