Writing

Feed Software, technology, sysadmin war stories, and more.

Thursday, April 19, 2018

More fun with C++ STL containers and []

Last week, I talked about the fun that you get when you hand a bad pointer to std::string, like from a bad [] access into a vector. Today, I have another bit of bracket operator fun in C++, but this time, it comes from map.

This one isn't one I found. It's something that someone else found and provided as a warning to others. Likewise, I will now share it with the world. This didn't happen to me, but it did happen to someone who was just doing their job and somehow tripped over it. That's called being human (see below).

Before you try to compile it, see if you can just eyeball it first. What does this code do? Does it compile? Does the compiler print any warnings? What if you use -Wall? If it runs, what does it print?

#include <stdio.h>
 
#include <map>
#include <string>
 
int main() {
  std::map<std::string, std::string> x;
  int i = 0x5001;
  x["foo"] = i;
 
  printf("%s", x["foo"].c_str());
 
  return 0;
}

Pretty nasty, right? You could already have this in your code without realizing it. If you're relying on some kind of warning or error, it's not good enough for this situation.

Pre-emptive responses: "Oh you shouldn't do that". No shit, sherlock. There's a bunch of stuff like this in computers. This is just one more of them. Do you know all of them? No way. Do I? Nope. Does anyone? I doubt it.

I'll say it again: people are going to make mistakes if bad systems let them. You can either complain about people being people, and try to reprogram every single one of them, including all of the new ones coming along every second, or you can build better systems that deal with humanity better. Get with the program, or start tilting at windmills. Just leave me out of it.

"It's supposed to do that". See above.

Incidentally, citing one of my posts and saying I'm "not a real C++ programmer" is just amazing. Who cares what you think?

Okay, now that we have that out of the way, what do you do about it? Well, you could try x.emplace(...) instead. Assuming you've already vaulted the hurdles to be able to run a sufficiently recent C++ everywhere, then indulge and enjoy. Otherwise, aim for x.insert and prepare to get verbose with std::make_pair and friends.