Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Here's a 2011 guide to modern C: [1] Discussed on YC last year.[2]

The 1970s string functions, such as "strcpy", that don't have a destination length were deprecated years ago, but they've never been removed from libraries. Microsoft's C compiler has warned about this for a decade.[3] This is one of the major causes of buffer overflows in C, and a large number of exploits involve it.. There's a CERT advisory from Homeland Security about "strcpy".[4] Seeing a "strcpy" in new code is a big red flag. If you see that in an interview, don't hire that programmer. They're dangerous.

Since C99, you've been able to write

    for (int i = 0; i < 10; ++i) ...
in C code, and that was in C++ from the early years. The trend in programming is strongly towards declaring and initializing variables at the same time. Remember, in C, local variables declared but not initialized have junk values until assigned. The "all variables declared at the top of a function" style is obsolete. Pointer variables declared without initialization are especially bad.

There's a long and painful history of classic C bugs, and the newer versions of C help, just a little, to avoid them.

[1] http://icube-icps.unistra.fr/img_auth.php/d/db/ModernC.pdf [2] https://news.ycombinator.com/item?id=9018247 [3] http://stackoverflow.com/questions/4012222/c-strcpy-gives-a-... [4] https://buildsecurityin.us-cert.gov/articles/knowledge/codin...



Playing devil's advocate: local variables declared but not initialized before being used will always generate a warning (which can be turned into a hard error) on modern optimizing compilers like gcc or clang.

And having all variables declared at the top of the function can make it easier to visualize how much stack space the function is using, which can be useful when your stack is limited to a few kilobytes.


IMHO strcpy() is perfectly fine if you know the length of the source, and ensure the destination is always big enough. strcpy() will always write strlen(src)+1 bytes, nothing more and nothing less. That said, code should be written so those facts are obvious, and documentation is a preferred way to show that. (Being explicit about whether null-terminators are included or not in length specifications is one thing that seems to be often overlooked, for example.)

Microsoft's _s functions don't help if you don't know what the lengths should be, and if you do, they just make it more confusing.


Yup, I'm gonna stick my neck out here and say I quite like strcpy()

In good code it spells out in one glance that there exists a guarantee on the size of the destination buffer.

Supplying the string's length just brings redundant code and, with it, ambiguity.

Discouraging strcpy() use is fine and understood; I'm aware of all the caveats and bugs and security implications.

But the kind of black-and-white thinking that says "always use strncpy instead of strcpy" is bad; the idea that truncating a string magically absolves us of any security implications or the need for exit paths.

And then let's look at how much code has made a mess of strncpy() whilst thinking it was doing the right thing.

I can probably count on one hand the number of times I've wanted to copy a string but been happy for it to be quietly trimmed, even in extreme cases. Whereas anything from alloca to flexible array member, or copying a string back to its original buffer, are all very appropriate use of strcpy().


  > Since C99, you've been able to write
  >
  >    for (int i = 0; i < 10; ++i)
To be fair, Microsoft's compiler only began supporting that recently, so for cross-platform compatible code, people often declared the index outside the loop.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: