On Thu, Mar 28, 2013 at 09:03:07PM +0100, Adam D. Ruppe wrote: > I was working on a project earlier today that stores IP addresses in > a database as a uint. For some reason though, some addresses were > coming out as 0.0.0.0, despite the fact that if(ip == 0) return; in > the only place it actually saves them (which was my first attempted > quick fix for the bug). > > Turns out the problem was this: > > if (arg == typeid(uint)) { > int e = va_arg!uint(_argptr); > a = to!string(e); > } > > > See, I copy/pasted it from the int check, but didn't update the type > on the left hand side. So it correctly pulled a uint out of the > varargs, but then assigned it to an int, which the compiler accepted > silently, so to!string() printed -blah instead of bigblah... which > then got truncated by the database, resulting in zero being stored.
IMO, the compiler should insert bounds checks in non-release mode when implicitly converting between signed and unsigned. Also, I don't like repeating types, precisely for this reason; if that second line had been written: auto e = va_arg!uint(_argptr); then this bug wouldn't have happened. But once you repeat 'uint' twice, there's the risk that you'll forget to update both instances when changing/copying the code. DRY is a good principle to live by when it comes to coding. > I've since changed it to be "auto e = ..." and it all works > correctly now. Yep! :) > Anyway I thought I'd share this just because one of the many times > bearophile has talked about this as a potentially buggy situation, I > was like "bah humbug"... and now I've actually been there! > > I still don't think I'm for changing the language though just > because of potential annoyances in other places unsigned works (such > as array.length) but at least I've actually felt the other side of > the argument in real world code now. Maybe it's time to introduce cast(signed) or cast(unsigned) to the language, as bearophile suggests? T -- Государство делает вид, что платит нам зарплату, а мы делаем вид, что работаем.