TIL: C++ character constants aren’t created equal


When reviewing a patchset involving files, strings, timers, and multiple threads (essentially all the “tough to review” checkboxes right there), a comment from :froydnj caught my eye:

> +const char* kPersistenceFileName = "gv_measurements.json";
> +const char* kPersistenceFileNameNoExt = "gv_measurements";

Please make these `const char kPersistence...[] = "..."`, which is slightly smaller on all of our usual systems.

Why? Aren’t C arrays just pointers to the first element? Don’t we treat char[] and char* identically when logging or appending them to higher-order string objects?

Influenced by :Dexter and :jan-erik, I tried this out myself. I made two small C programs arr.c and ptr.c where the only difference was that one had a const char* and the other a const char[].

I compiled them both with gcc and then checked their sizes in bytes.arrPtrSizes

Sure enough, though ptr.c was smaller by one byte (* is one character and [] is two), after being compiled ptr was larger by a whole 8 bytes!

This is because C arrays aren’t identical to pointers to the first element. Instead they are identifiers that are (most of the time) implicitly converted to be pointers to the first element. For instance, if you’re calling a function void foo(char c[]), inside the function `c` is implicitly a char* and its size is that of a pointer, but outside of the function c could be an array with its size being the length of the array. As an example:

void foo(char c[]) {
  printf("sizeof(c): %d\n", sizeof c);
int main(void) {
  char arr[] = "a";
  printf("sizeof(arr): %d\n", sizeof arr);
  return 0;


sizeof(arr): 2
sizeof(c): 8

Another way to think about this is that the char* form allocates two things: the actual string of four (“abc” plus “\0”) characters, and a pointer called ptr that contains the address of the place the ‘a’ character is stored.

This is in contrast to the char[] form which allocates just the four-character string and allows you to use the name arr to refer to the place the ‘a’ character is stored.

So, in conclusion, if you want to save yourself a pointer’s width on your constant strings, you may wish to declare them as char[] instead of char*.


(( :glandium wrote a much deeper look at this problem if you’d like to see how much worse this can actually get thanks to relocations and symbol exporting ))

(( :bsmedberg wrote in to mention that you almost never want const char* for a constant anyway as the pointer isn’t const, only the data is. ))


Mozilla All-Hands Tips

All Hands Austin, December 2017, Mitchell Baker presenting. (Photo used under CC BY-NC-SA 2.0)

Twice a year, Mozilla gathers employees, volunteers, and assorted hangers-on in a single place to have a week of planning, working, and socializing. Being as distributed an organization as we are, it’s a bit rare to get enough of us in a single place to generate the kind of cross-talk and beneficial synergistic happenstances that help us work smarter and move in more-or-less the same direction. These are our All Hands events.

They’re a Pretty Big Deal(tm).

So here you are, individual contributor or manager, staff or volunteer, veteran or first-timer. With all these Big Plans, what are we littler folk to do to not become overwhelmed?

I have some tips.

Before You Go

Set up a mail folder/label for relevant email: You’ll be getting some email with details about where you should be, what you should be doing, and when. Organizing these into one place is helpful for reference, so come up with a label (maybe “201807-sanfran” or “mozsf2” or “fogzilla” or something) and organize those emails as they come in.

Act on those emails immediately: If they contain instructions or an announcement that bookings or registration is now open… then do that thing right then. Do not file the email and forget. Do the thing while you are looking at that email. Only then should you file that email and get back to where you were in your brain. If you absolutely can’t just then (have to synchronize with family or what-have-you), put a calendar reminder in that repeats every weekday until you handle it.

Do not upgrade Nightly: You’re running Nightly, right? You’ll be travelling through a land of uncertain connectivity, and the last thing you want is to use it downloading a multi-MB Nightly update that might have accidentally disabled Captive Portal Detection. If it works, keep your Nightly build until you’re certain you have the bandwidth to download a new one. All else fails, keep it until you get back.

Make sure your laptop is in shape: My laptop is often neglected in favour of its Desktop comrade: updates may be pending, credentials may have expired, the source code checkouts might be weeks old, and there may have even been a new version of Mozilla Build released since the last time I tried to compile Firefox. With luck, while at an All Hands you won’t have to compile Gecko on a laptop in your hotel… but we make our own luck, we who are prepared. Prepare your laptop.

Prepare your family: If you don’t live alone, you’ll have non-mozilla prepwork to do. Spouse and kids or roomates and pets, there are lifeforms who normally expect to see you that won’t. Clear the family schedule for the week you’re gone, and do as much preparation ahead of time as you can. Laundry, meal planning, groceries, sitters, dog walkers, even lawn services are things you can arrange to lighten the load that your absence will place on those around you. Even if you’re bringing them with you.

While You’re There

Do not fear missing out: You will not be able to attend both Boardgame Night and your team dinner. There will be karaoke parties you won’t get to, or be invited to. This is fine. This is expected. This is unavoidable when you have so many people disorganizing so many things simultaneously. So don’t fret about it. Prioritize.

Say no: Speaking of prioritizing: prioritize for yourself. You may very well be operating as a Level 100 You for hours at a time. So many people to talk to, so many talks and social events to organize, deliver, and attend… No. You don’t have to stay the entire length of the party. You don’t even have to go. If you feel yourself fading, get out while you have the strength. Regroup. Find a quiet corner or go to sleep early… At my first All Hands, I napped on both Wednesday and Thursday. And I wasn’t even in a different timezone. It really helped.

Wash your hands: Lots. Before meals. After meals. You’ll be talking, working, eating, and otherwise hanging out with a thousand of your closest coworkers. It’s probably your best bet for not catching mozflu, and it’s definitely your best bet to not transmit it.

After You’re Back

Consider taking a day: Generally speaking you’ll be flying back on Saturday and returning to work on Monday. Depending on distance to travel, available flight times, and cancellations, this may result in only a few hours between stumbling through your door and stumbling back to work. Consider booking that Monday off (or, honestly, if your trip back was heinous, don’t even book it off. Just take it. Get some sleep. Work can wait until Tuesday.)

Check in: If you live with family, you haven’t seen them for a week. Even if you brought them with you, you’ve been in meetings and talks and stuff most hours. Check in with them. Get up to speed on what’s been happening in their lives while you’ve been away.

Get excited for the next one: Even immediately back from an All Hands, it’s still only six months to the next one. Take stock of what you liked and what you didn’t like about this one. Rest up, and try not to get impatient :)


(( Great minds think alike, because Seburo recently wrote a Wiki article covering even more excellent tips for All Hands events. Check that out, too! ))

So I’ve finished Mario + Rabbids Kingdom Battle

I expected a game that gave Mario a gun to be less bland. XCOM: Mushroom Kingdom this isn’t. Nintendo characters, but without Nintendo-levels of polish.

All that pithily said, I still enjoyed it. Especially when I started thinking about it more like a small-screen puzzle game than a big-screen campaign.

It went on about two levels longer than it ought to have done. And I was never given an incentive to use the different characters. And I swear it ate through my Switch’s battery faster than Zelda (and Zelda had a lot more to do each frame, I would think).

But it was fun. Bouncing and drop-kicking and taking pipes really adds to a feeling of mobility. The choice to not measure movement range in path length but in radius made things much more predictable. And the puzzles (once I saw them that way) were engaging and interesting to pull apart.

I could’ve used a “whoops, wrong button” one-step undo. And I’m still not sure which of the shoulder buttons is L and which is ZL (and this game uses them more than the d-pad buttons).

But overall, not a waste of the, say, 15 hours I put into it.

Annoying Graphs: Did the Facebook Container Add-on Result in More New Firefox Profiles?

Yesterday, Mozilla was in the news again for releasing a Firefox add-on called Facebook Container. The work of (amongst others) :groovecoder, :pdol, :pdehaan, :rfeeley, :tanvi, and :jkt, Facebook Container puts Facebook in a little box and doesn’t let it see what else you do on the web.

You can try it out right now if you’d like. It’s really just as simple as going to the Facebook Container page on addons.mozilla.org and clicking on the “+ Add to Firefox” button. From then on Facebook will only be able to track you with their cookies while you are actually visiting Facebook.

It’s easy-to-use, open source, and incredibly timely. So it quickly hit the usual nerdy corners of the web… but then it spread. Even Forbes picked it up. We started seeing incredible numbers of hits on the blogpost (I don’t have plots for that, sorry).

With all this positive press did we see any additional new Firefox users because of it?

Normally this is where I trot out the usual gimmick “Well, it depends on how you word the question.” “Additional” compared to what, exactly? Compared to the day before? The same day a week ago? A month ago?

In this case it really doesn’t depend. I can’t tell, no matter how I word the question. And this annoys me.

I mean, look at these graphs:

Here’s one showing the new-profile pings we receive each minute of some interesting days:c52dd445-e624-47aa-a44d-d5e758b56b04

Summer Time lining up with Daylight Saving Time means that different parts of the world were installing Firefox at different times of the day. The shapes of the curves don’t line up, making it impossible to compare between days.

So here’s one showing the number of new-profile pings we received each day this month:ebce02bb-1c78-4c52-9878-9a9e8d78e459

Yesterday’s numbers are low comparing to other Tuesdays these past four weeks, but look at how low Monday’s numbers are! Clearly this is some weird kinda week, making it impossible to compare between weeks.

So here’s one showing approximate Firefox client counts of last April:1d44c744-0267-4216-9371-5bf042ba47e7

This highlights a seasonal depression starting the week of April 10 similar to the one shown in the previous plot. This is expected since we’re in the weeks surrounding Easter… but why did I look at last April instead of last March? Easter changes its position relative to the civil calendar, making it impossible to compare between years.

So, did we see any additional new Firefox users thanks to all of the hard work put into Facebook Container?



TIL: Water Softeners

We wake up to hear an odd sound carried through the forced-air ducts. Furnace is loud, I think. My wife precedes me downstairs and, finding the sound louder, heads to the basement.

“Water in the basement!” comes her yell. I bound down the stairs two at a time and start shutting off water valves to stem the flow of a 3/4″ coldwater supply emptying through the water softener and onto the floor.

Water softeners are a piece of almost necessary equipment in the part of Canada where I live. Hard water is water that contains dissolved minerals (usually Calcium and Manganese) that, when present in sufficient amounts, can form “hard water scale.” This usually shows up on heating surfaces (the inside of kettles and water heaters) and on drying dishes (in the form of cloudy spots). Hard water’s not toxic or anything, but it’s a pain, and our water’s well into the category the USGS calls “very hard.” So we soften it.

Conventional water softeners work by exchanging those dissolved mineral ions (mostly Calcium around here) for salt ions (Sodium or Potassium) in tiny little resin beads kept in a column called the “resin tank” (or “mineral tank”) which you hook up to your water supply. The beads are made up of a compound to which salt binds less strongly than other ions (because it prefers ions missing two valence electrons, if you remember your High School Chemistry). Thus, when a bead with a bound salt is presented with a free-floating Calcium ion, the bead ditches the salt into the water and snatches up the Calcium.

The resulting water does not taste salty and does not meaningfully contribute to dietary salt intake, in case you were wondering.

Eventually these beads become full of these mineral ions. To return them to previous performance levels, they are soaked and flushed with a salt brine. Due to the brine’s high concentration of salt ions, the hardness ions leave the resins to form an equilibrium between the beads and the brine. Then the waste brine (now full of hardness ions as well as quite a lot of the salt) is sent down the drain.

To generate the brine, water is pumped into a salt storage tank (or “brine tank”) and then is left to dissolve salt. This salt is the only consumed quantity in this process, and must be regularly topped up (usually by purchasing 24kg bags of softener salt pellets at local grocery stores for under $6 a bag).

The whole recharge process takes about two hours.

Water softeners have an operating lifetime similar to that of the plumbing fittings you need to install it: ten to fifteen years.

Near as I can figure it, the water softener that decided to flood my basement was 14 years old when its resin tank decided to rupture catastrophically during a 2am recharge cycle. Two hours later, recharge cycle complete, it flipped the valve back to supply the house with soft water and then supplied itself with all of the house’s water.

Luckily my floor drain was nearby and could handle the water flow, so the only “damage” was a little splashed carpet in the next room and some garbage I’d been meaning to throw out. I’m not looking forward to the water bill next month, but I’m happy my furnace is installed on feet for just this sort of occasion.

I did get a nice close-up view of those tiny ion-exchange resin beads, though, as they had been spread all over the basement floor. They look like transparent cornmeal. When wet they kinda have the consistency of mashed potatoes.

One on-sale water softener from Canadian Tire and one plumber’s visit later, I’m once again living in the land of soft water. For the next ten to fifteen years.

So now I know rather more than I previously did about water softening. And so do you.


So I’ve Finished The Legend of Zelda: Breath of the Wild


Wow, what a game. It’s a game that had me talking with friends about video games again. You know, in that cagey way where you hint at something you aren’t sure they’ve seen yet until they nod and then you head into spoiler territory?

It’s a game that gives you every tool you need in the tutorial. Swords, shields, bows, bombs… and then you’re off. It doesn’t care what you do from then on, or how you do it. You simply go.

It’s a game that decides to not measure progress. Sure, it’ll count shrines and things… but it doesn’t care. Nothing changes, nothing matters except defeating Ganon. And yet, it is happy to let you take the long way around to get there, both in mechanics and in story. Who needs experience points, or levels, or priority missions, anyway?

It’s not perfect. The framerate drops in the Great Hyrule Forest. It leans a little hard on motion controls that ask you to point with the bottom of the controller instead of the point. Inside the Divine Beasts voices lead you around by the nose as though they didn’t get the “trust the player” memo the rest of the game hinges upon.

And the entire Gerudo segment comes across as tone deaf. Treating an ancient culture’s mores as a puzzle to “solve” because you know “better” is a little colonial for the 21st Century.

But then you hold these stumbles up to moments like when the Deku tree says “Next time I’ll let you kill yourself on that sword” and you believe it. The game has been honest with you so far, trusting you and being trusted almost to a fault. I believed that tree about that sword.

Speaking of that sword, pulling it was billed as a test of strength. “Strength?” There are no character sheets in Breath of the Wild, what is strength? Strength is the number of hearts you have. You are stronger when you have more heart. WHAT.

I’m especially pleased with this game coming straight off of Mass Effect: Andromeda. The cartoon characters you meet in Hyrule are different and recognizably so from their design. Even the hapless travellers you rescue time and time again are expressive in text and in facial expression.

ME:A also never wanted to let the player fail. Zelda is only too happy to have you fail. Too close to your own bomb when it goes off? Congratulations, you ragdolled down a cliff and into the river. Find a guardian? They’ll roflstomp you for hours. And you keep running across them! Even the main quest has you tromping up a hill in Zora’s Domain and finding something you cannot win against. Not because the game has decided it, but because you’re just not ready. And you can brickwall against it, like I did. Maybe if you jump over here, maybe if you use lightning arrows… Nope. You aren’t supposed to win this fight. You are the mouse, not the lion (or in this case, the Lynel). Scurry, little mouse, and try not to be seen.

Oh. No. You’ve been seen. Better run, little mouse. Run!

I’m sure there’s a wave of people who’ve seen this first in games like Dark Souls, but for me Zelda: Breath of the Wild was the first game in recent memory that made me afraid.

And how I love it for doing so.

Attacking Hyrule Castle, pushing deeper within. Everything the world taught you being put to the test, but upside down. On the overworld height helps you find your way, lets you see danger coming. In the Castle, height will get you killed. Better run, little mouse.

Wait. No. You’re not a mouse any more. You’ve fought, you’ve learned, you’ve grown.

But… you still remember being a mouse. So the tension ratchets up more than it ought to, creatures down the hall loom a little larger than they actually are, and victory… oh, victory tastes so much sweeter when you remember how impossible it used to be.

And then you reach Ganon. They really didn’t mind being a little disgusting with the creature design of the calamity bosses, and Ganon got a double dose. I feel a little cheap not having learned the perfect parry before fighting him, having to rely on my powers to defeat him… but that’s fitting. It works with the story. The champions were there for the assist.

Or so I tell myself.

The ending… was fine. The writing was a little weak, but everything else was lovely. I’m a little disappointed I don’t get to play in the world my adventure helped create, instead being dumped outside the castle gates, moments before the final confrontation, but it was an end.

And so I decided to put Zelda: Breath of the Wild down. I feel I could spend a lot more time in there. I feel I may have played it “wrong” by rushing too much to expand the map without exploring it enough (and my final map percentage of 40.03% certainly seems to reflect that). I can think of, right now, another couple of corners of the map I maybe should’ve gotten to.

But some things should end. Some things should leave you with that bittersweet hangover of a world your mind isn’t finished living within.

It’s been a long time since I’ve felt that from a video game. I missed it.

TIL: Feature Detection in Windows using GetProcAddress

In JavaScript, if you want to use a function that was introduced only in certain versions of browsers, you use Feature Detection. For example, you can ask “Hey, browser, do you have a function called `includes` on Array?” If the browser has it, you use it; and if it doesn’t, you either get along without it or load your own implementation.

It turns out that this same concept can be (and, in Firefox, is) done with Windows APIs.

Firefox for Windows is built against the Windows 10 SDK. This means the compiler knows the API calls and type definitions for all sorts of wondrous modern features like toast notifications and enumerating graphics adapters in a specific order.

However, as of writing, Firefox for Windows supports Windows 7 and up. What would happen if Firefox tried to use those fancy new Windows 10 features when running on Windows 7?

Well, at compile time (when Mozilla builds Firefox), it knows everything it needs to about the sizes and names of things used in the new features thanks to the SDK. At runtime (when a user runs Firefox), it needs to ask Windows at what address exactly all of those fancy new features live so that it can use them.

If Firefox can’t find a feature it expects to be there, it won’t start. We want Firefox to start, though, and we want to use the new features when available. So how do we both use the new feature (if it’s there) and not (if it’s not)?

Windows provides an API called GetProcAddress that allows the running program to perform some Feature Detection. It is asking Windows “Hey, so I’m looking for the address of this fancy new feature named FancyNewAPI. Do you know where that is?”. Windows will either reply “No, sorry” at which point you work around it, or “Yes, it’s over at address X” at which point to convert address X into a function pointer that takes the same number and types of arguments that the documentation said it takes and then instruct your program to jump into it and start executing.

We use this in Firefox to detect gamepad input modules, cancelable synchronous IO, display density measurements, and a whole bunch of graphics and media acceleration stuff.

And today (well, yesterday at this point) I learned about it. And now so have you.


–edited to remove incorrect note that GetProcAddress started in WinXP– :aklotz noted that GetProcAddress has been around since ancient times, MSDN just periodically updates its “Minimum Supported Release” fields to drop older versions.