char Dest[BUFLEN] = "\0"; char Src[] = "BlahBlah"; strncpy(Dest + 1, Src, BUFLEN);
The result of careless size-specifying in `strncpy' overflows the buffer and then later causes core dump; since my wrong understanding that `strncpy' writes at most 9 bytes(length of "BlahBlah" plus the null byte) and the bug only appears when the memory usage be complex enough, it takes me lot of time to find out and the decision to rethink the C-style string.
C-style string
C uses Null-terminating character array as its string structure. Only the header position and the convinced-existing null byte represents the string. It is, in my opinion, one of the early `abstract' type: it is the concept without considering any actual memory management issues. Due to the design of C-string, it is easy and effective to truncate a string: just move the header or null-byte to right or left truncates, still, without considering memory management. On the other hand, since the header position and null-bytes are such essential to the string, a series of string operating function is necessary.C-String operating functions
There are a series of string operating functions with names begin from `str', excluding the`strn' prefix, such as strcpy, strcmp, strcat... etc, which are defined in string.h. These string operating functions do the operations to a complete C-style string: every character byte from the string header to the nearest null byte. By the layout of C-string, the length of string is not obvious and relatively expensive to get. Moreover, such important role of null byte in string is actually uncertain when handing a string header, a series of functions with memory concept are there.`strn'-series functions
The `strn'-series functions involve the length condition within the string operations: either the null byte meets or the specified length arrives would stop the operatons. It not only makes intuition protection in memory on load, but also breaks the rule and layout of C-string. The functions produce the possibility of constructing, modifying, and operating in a non-C-string, or incomplete-C-string, without notifying. Thus a well-setting c-string might results broken C-strings, rather than truncated since the result might not null-terminated. As these functions are more friendly to memory management than string operations, it would be called by `string buffer operating functions' instead of `string operating functions'. It's all for buffer.strncpy
Furthermore for breaking the C-string(or truncating the character array), strncpy also tail-fills the null bytes if the source string is shorter than the specified size: the reason of the bug at beginning. I could not find the actual why for the behavior so far, but it is defined clearly in the specification of C. It not only breaks the elegant of the null byte, but also downgrades the performance at all. Some of the supporters declare the tail-filling makes the buffer `clean', avoiding the buffer reusing issues, but it should not be something like:memset(Dest, 0, BUFLEN); non_tail_filling_strncpy(Dest, Src, BUFLEN);
instead, if the left data in Dest be classified?
Conclusion
There should be a lot of suggestions and alternatives over the internet if searching `strncpy': strlcpy, std::string...etc. I agree that C-string, or the special-byte-terminated array, has its own problems and difficulties, but it is still a classical and charming design for me, even discarding the historical backgrounds and the effects. It provides a typical C type as it was, and preserves the characteristic as it should be.Reference
Null-terminating String.Google: strncpy.
沒有留言:
張貼留言