Mapnik Compilation warning C4172: returning address of local variable or temporary?
Has anyone experienced these warnings around compiling the color files (eg css_color_grammar.cpp; color.cpp) when building Mapnik?
warning C4172: returning address of local variable or temporary
They seem to occur in boost phoenix header files eg meta_grammar.hpp,actor_operator_10.hpp etc.
I suspect (following discussions over on mapnik) that they are causing access violation errors (when inline functions are enabled - mangled strings when disabled) I am experiencing with outputting the color to a hex string using the karma generator but am just wondering if other people experience these warnings too?
Yes, I've seen these warnings. Because they are coming out of boost (not mapnik) I had not paid much attention, but yes we should take a closer look to make sure they are not happening due to Mapnik usage. /cc @artemp
Do these occur when karma attributes are assigned references instead of temporaries?
diff --git a/src/color.cpp b/src/color.cpp
index 2dcbe76..2a35353 100644
--- a/src/color.cpp
+++ b/src/color.cpp
@@ -85,10 +85,10 @@ std::string color::to_hex_string() const
karma::generate(sink,
// begin grammar
'#'
- << right_align(2,'0')[hex[_1 = red()]]
- << right_align(2,'0')[hex[_1 = green()]]
- << right_align(2,'0')[hex[_1 = blue()]]
- << eps(alpha() < 255) << right_align(2,'0')[hex [_1 = alpha()]]
+ << right_align(2,'0')[hex[_1 = red_]]
+ << right_align(2,'0')[hex[_1 = green_]]
+ << right_align(2,'0')[hex[_1 = blue_]]
+ << eps(alpha() < 255) << right_align(2,'0')[hex [_1 = alpha_]]
// end grammar
);
return str;
I recently left a reply on the mapnik issues thread. I think I directly caused the error when I was modifying a patch. I had left in a BOOST_SPIRIT_UNICODE pragma in value.hpp which, when taken out, stopped the access violation when inlining was renabled and the garbled strings when it wasn't.
I had previously tried a number of things including what you suggested but nothing seemed to stop the error, It was only when I recompared my changes to the current codebase that I realised the extra pragma was still there.
I haven't closed the issue as the compiler warnings are still there even though they don't seem to have caused my problem. If it's not seen as a big deal though I don't mind if it is closed.
I'm asking because I'm not sure what exactly [_1 = red()] does. If it copies the value, then fine. If it binds a reference to it, then fine, standard says reference extends the lifetime of the temporary; but it might trigger the warning, and in that case we can get rid of it by using red_ instead. If it stores a pointer to the rvalue, then that is a problem; but I think if that was the case, you'd see bogus output.
Anyway, I will probably rewrite at least color::to_hex_string, karma is plain overkill for something that could be 5 lines of C.
Anyway, I will probably rewrite at least color::to_hex_string, karma is plain overkill for something that could be 5 lines of C.
@lightmare @artemp might complain, but I'm a big :+1: :) That would allow us to drop compile time for color.cpp significantly
@springmeyer - not so quick :) . Remember, mapnik is C++ not C !! @lightmare
Anyway, I will probably rewrite at least color::to_hex_string, karma is plain overkill for something that could be 5 lines of C.
What? I'm not even mildly convinced by your statement but I'd like to see your 5 lines in C proposal
ref : http://www.boost.org/doc/libs/1_60_0/libs/spirit/doc/html/spirit/karma/tutorials/quick_start.html
@lightmare @springmeyer - I think colour generators don't need a phoenix dust, I'll take a look at simplifying.
For what it's worth, while I was trying to figure out what was causing my problem I did rewrite the color::to_hex_string function. It's not 5 lines but it is less than 10 and seems to work :)
std::string color::to_hex_string() const
{
std::stringstream stream;
stream << "#";
stream << std::setfill('0') << std::setw(2) << std::hex << 0u + red(); // implicit cast to unsigned int before hex conversion
stream << std::setfill('0') << std::setw(2) << std::hex << 0u + green();
stream << std::setfill('0') << std::setw(2) << std::hex << 0u + blue();
if (alpha() < 255) {
stream << std::setfill('0') << std::setw(2) << std::hex << 0u + alpha();
}
return stream.str();
}
@jc101 - the approach above works but I prefer boost::karma :)
could you try https://github.com/mapnik/mapnik/commit/3e8ee9a55929498360bc1ab42a187a17f6f4e160 and see if warning are gone, pls ?
I'd like to see your 5 lines in C proposal
:dart: touche! That was unfairly exaggerated, not sure why I imagined color stored as uint8_t[3] and no alpha, that would be possible in 7 lines (almost C :cake: )
static char const xdigits[] = "0123456789abcdef";
char buf[7] = {'#'};
for (int i = 0; i < 3; ++i) {
buf[1 + 2 * i] = xdigits[(c[i] >> 4) & 15];
buf[2 + 2 * i] = xdigits[c[i] & 15];
}
return std::string(buf, 7);
Here's a real, 15-line body version
std::string color::to_hex_string() const
{
static char const xdigits[] = "0123456789abcdef";
char buf[9];
buf[0] = '#';
buf[1] = xdigits[(red_ >> 4) & 15];
buf[2] = xdigits[red_ & 15];
buf[3] = xdigits[(green_ >> 4) & 15];
buf[4] = xdigits[green_ & 15];
buf[5] = xdigits[(blue_ >> 4) & 15];
buf[6] = xdigits[blue_ & 15];
if (alpha_ == 255) {
return std::string(buf, 7);
}
buf[7] = xdigits[(alpha_ >> 4) & 15];
buf[8] = xdigits[alpha_ & 15];
return std::string(buf, 9);
}
@lightmare - :clap: you get :trophy: :smiley_cat: ! On a serious note - I still prefer to use boost::spirit for parsing/generating output in mapnik rather than resorting to handwriting parser/generators. I'm thinking long term stability, readability, consistency etc etc.
@lightmare - here is a real challenge => apply_markers_multi
src/renderer_common/render_markers_symbolizer.cpp
Command execution time: src/renderer_common/render_markers_symbolizer.os: 136.205251 seconds
It would be super awesome to fix that ^. I know you have looked already but anything else we can do to improve? In any case should we at least split void operator() (T const& mark) const into separate *.cpp ?
I still prefer to use boost::spirit for parsing/generating output in mapnik rather than resorting to handwriting parser/generators.
I've been pondering handwriting spirit::qi::parser hexcolor for a few weeks, as I don't find the grammar particularly readable. I think hexcolor should be a single token in the grammar; whether written in spirit, handwritten or re2c generated, doesn't matter; but it's something so small and rigid that I prefer a handwritten parser that compiles in no time. Complex spirit grammars are fun :roller_coaster: Grammar for 3, 4, 6 or 8 hex digits... not for me :stuck_out_tongue_winking_eye:
src/renderer_common/render_markers_symbolizer.cpp
Yea, I stopped there. Separating the operators might help, as they require different apply_markers_multi overloads; haven't tried that, though.
@artemp I tried the changes you made and the warnings are gone; fyi they still exist on two files: css_color_grammar.cpp and css_color.cpp.