4 ms·
From the article: >In order to use these functions correctly you have to do this sort of nonsense. char buffer[5]; strncpy(buffer, “Thisisalongstring”
by primitur 14y ago
From the article:
>In order to use these functions correctly you have to do this sort of nonsense.
char buffer[5];
strncpy(buffer, “Thisisalongstring”, sizeof(buffer));
buffer[sizeof(buffer)-1] = 0;
Actually, its more like this:
char buffer[5] = {0};
strncpy(buffer, "This is a long string", sizeof buffer - sizeof buffer[0]);
(edit: sizeof, not sizeof()! edit2: bugfix!)
But okay, maybe your compiler won't let you do that (it should). Oh. We've already touched on what Microsoft won't let you do .. maybe Microsoft won't let you do that. (In which case the answer should be: don't use Microsoft).
But anyway .. then the author says this:
>We are programmers, are we not? If the functions we are given to deal with strings are difficult to use correctly then we should write new ones.
Umm: NO! Learn to use your tools properly and stop re-inventing the wheel to fit your misunderstanding of the world! BILLIONS of lines of code out there use strncpy() and other n-fn variants, and guess what: even in safety-critical, life-threatening, embedded environments!
This article should really be titled: "If you are going to use strncpy(), and you're scared of it, THEN DON'T DEPLOY WITHOUT FULL CODE COVERAGE TESTING!"
NB: edit2 GOTCHA! Coverage, people.
- Aloisius 14y agoMmm... that will fail since the last character is not null. Change: char buffer[5] = {0}; strncpy(buffer, "This is a long string", sizeof buffer); to: char buffer[5] = {0}; strncpy(buffer, "This is a long string", sizeof(buffer) - 1); (I find sizeof() to be clearer than just sizeof in this case since "sizeof buffer - 1" looks awfully strange.
- primitur 14y agoPop quiz: is sizeof a function? (Hint, no, its an operator. Like -- and &. Do you prefer this form: --(someint);
- Aloisius 14y agoRegardless, it still looks better with parenthesis and removing them serves no real benefit other than proving that I know it is an unary operator. Feel free to grep through your /usr/include for sizeof and see which way is more common.
- dibbit 14y agoThere actually is a good reason not to use parens with sizeof, and it is in fact a means of introducing subtle bugs to your code if you don't know the difference: sizeof some_struct; //computed at *compile* time sizeof(some_struct); // also computed at *compile* time, but looks like its a runtime call Anything that looks like something but isn't actually that thing, in my opinion - especially with a language like C - is room for programmer enlightement ..
- dchichkov 14y agoJust FYI - code: sizeof buffer - sizeof(buffer[0]) is looking unconventional. Couple of reasons... You generally want to avoid +1 / -1 in your code. You don't want to write sizeof() without parenthesis, - it reduces readability.
- pitkali 14y agoPop quiz: what are possible results of running sizeof(char)? It's just another thing to note ;)
- maximilianburke 14y agoThe languages state that sizeof requires parentheses when the expression is the name of a type -- sizeof int is an error, sizeof(int) is not.
- jibsen 14y agoI think perhaps confusion on the use of parenthesis comes from the fact that you need them for types and not for objects.
- pitkali 14y agoI like the consistency of using parenthesis always. Just like some people insist of putting them in logical statements even if they do not affect the order of evaluation in that particular case.
- Dylan16807 14y agoIt's an operator but nobody should be forced to remember that it's an operator when it doesn't matter.
- dibbit 14y agoIt does matter. sizeof is computed at compile time, it is not computed at runtime. something() is a runtime invocation .. sizeof() 'looks' like that, but isn't.
- Dylan16807 14y ago1. A lot of math gets computed at compile time. 2. sizeof is not necessarily done at compile time. C99 allows variable-sized automatic arrays, forcing it to store and later look up the value at runtime if you use sizeof.
- btbuilder 14y agoedit: parent didn't originally - 1 from sizeof. Except you just failed to null-terminate your string, good job at proving the truth of the article :) #include <stdio.h> #include <string.h> int main(void) { char buffer[5] = {0}; strncpy(buffer, "This is a long string", sizeof(buffer)); printf("%s\n", buffer); } $ ./test This ^`gh?
- primitur 14y ago$ cat /tmp/t.c #include <stdio.h> #include <string.h> char buffer[5] = {0}; int main(int argc, char argv) { strncpy(buffer, "This is a long string", sizeof buffer - sizeof buffer[0]); printf("The string: [%s] The len: %ld\n", buffer, sizeof buffer); } $ /tmp/t The string: [This] The len: 5 $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.6.3 edit: oops. Coverage before Coffee!
- Aloisius 14y agoThe string: [This ] The len: 5 Doesn't it bother you that your 5 character long buffer that is supposed to be terminated by a null happens to have 5 characters in it "[This ]" instead of 4 visible "[This]"? Your memory just happens to have a null 6 bytes after the pointer.
- dibbit 14y agoRun the code and see for yourself, parent fixed it.
- lmm 14y agoTesting, even full coverage testing (a perversion of a good idea if ever I saw one), cannot and will not catch all errors. It is not a substitute for better programming techniques, and certainly not a reason to avoid using them.
- dibbit 14y agoMaybe, but it will catch bugs like this if the test is written for it, and anyone writing C in the 21st century professionally, with safety in mind, is a) writing tests, and b) getting 100% coverage.