There are numerous versions of the basic copy function, too many now. some of the new versions are declared safer because they incorporate a limiting count value. However, all the ones I have tried and inadvertenly tested just crash the application. I find that rather rude.
Are there any versions of ...cpy...() and ...printf...() that limit the count of characters copied to the space found in the destination string. Without an ungracefull app crash?
Are there any versions of ...cpy...() and ...printf...() that limit the count of
characters copied to the space found in the destination string.
Without an ungracefull app crash?
Unfortunately, No. Strcpy and printf are two of the most common functions that hackers use to exploit programming errors to "hack" into a program. When using these functions you need to pay extra attention to the size of your memory buffers and the actions you are performing on them.
You may have better luck with the C++ Standard Library.
The std::string class will manage your memory buffers, copies and concatenations.
std::cout doesn't have the program crash issues that you are running into.
In that case I wish to go on record as saying that we need a new set of these functions. These functions should be named ...strcpy_l(...) and ...printf_l(...), with the "l" (lower case L) standing for Limited. Under the covers, the function will examine the destination, determine the length of the destination, and quietly refuse to move more characters than the destination string can hold.
These will do what you are asking. Read the descriptions though, strncpy will not NULL terminate your string if it can't write all of the data to the buffer. This would open yourself up to another set of possibilities to crash your program.
I think both strncpy() and snprintf() sucks. Once I searched for hours for a bug that was caused by strncpy(). Here is the problem: strncpy() is suboptimal because even if you copy a 1 byte string, it fills the whole remaining part of the destination buffer with zeros unnecessarily, and on the other hand it doesn't zero terminate the string if its length equals to or bigger than the size of the dest buffer. The missing zero terminator character in similar cases is true for snprintf() too. I highly discourage everyone from using these functions.
Here is my opinion: strcpy is totally useless and totally unsafe. Use a string class in C++ and assign one string to another instead of strcpy. You can even implement refcounting if you write your own string class and then assignment will be super fast. You can of course use std::string for your needs.
If you write you own string class or if you extend your own string class from std::string then you can put in a format and vformat function (similarly to the MFC CString class) and you can do formatting so that the buffer size will be managed automatically for you. Here is an example to that: How to Format a String[^]. I would mention only one thing regarding this formatting function in the link: The use of the std::vector is unnecessary, you could put the string formatting directly to the string. even in that case the string resizing unnecessarily fills the whole string with a fill character before formatting the string into its buffer. With a custom string you can write more optimal code for this task.
The type safety of format parameters with the vararg nature of format functions is still endangering your program. Using the bad parameter types make your program crash at runtime when the formatting code gets executed. Example to a buggy formatting statement: format("Name: %s\n", 5). Gcc has an __attribute__ format printf to defend against such mistakes at compile time. You can mark you format function with this attribute and then gcc will catch such errors, it would find out for exmple that "%s" and 5 are not compatible. Unfortunately visual C++ doesn't have such feature but our current project is crossplatform so we compile it with both VC++ and gcc and this gcc feature is priceless.
Unfortunately this kind of formatting is too widespread and comfortable without similarly comfortable alternatives so this wont be dropped easily from C++. However a feature like the one gcc has can make this stuff quite usable and safe.