Live data from Hacker News

Linux eliminates the strncpy API after six years of work, 360 patches

phoronix.com

141–150 of 340 posts

Re: Linux eliminates the strncpy API after six years of work, 360 patches

#141

I have in the past made fun of the Linux kernel devs, supposedly some of the best C developers in the world, for not knowing how to make stringbuffer and stringview types, but to be fair to them we didn't have the consensus we have today on the topic. You know who did have the right idea though? Dennis Ritchie, who proposed a fat pointer type for C all the way back in 1990. Would have made for a perfect addition to C…

That only goes to show where WG14 priorities are.

Re: Linux eliminates the strncpy API after six years of work, 360 patches

#142

the zero terminated string is I think is computing's biggest mistake. Pascal style strings were much safer.

> Pascal style strings were much safer. The limitations were brutal. Initially you could only have 255 bytes in a string. The length of a string and the size of the allocation are now separate and you may need to think about that unused memory in your design. The problem now doubles with the introduction of UTF-8. Your string size is in bytes and you need to track characters separately. If you want to create an array…

All those limitations were sorted out in 1978 with Modula-2 and open arrays, aka spans.

What about the UNIX and C folks propaganda of C being the first systems language, or always focusing on the original Pascal used for teaching and not everything else that followed up with Mesa, Modula-2, Ada, Object Pascal and friends, none of them with said limitations.

Re: Linux eliminates the strncpy API after six years of work, 360 patches

#143
post #39
post #26

I wonder, why not use a string buffer paired with its length? For example, maybe use struct that has char pointer, and 2 ints (occupied length + total buffer length). Almost like c++'s std::string. This null terminator thing really sucks, it's potentially insecure and often unperformant.

Pascal did/does this, but eventually someone wants a string longer than the size portion can handle. Or wants the number of characters not the number of bytes.

And then anyone that isn't stuck in 1976 will use open arrays.

Re: Linux eliminates the strncpy API after six years of work, 360 patches

#145
post #98
post #75

The purpose of strncpy, which was originally part of the UNIX kernel code, was to copy file names to and from directory entries that consisted of a 2 byte inode number and a 14 byte zero-padded but not zero-terminated name field. I started warning my colleagues against using it the moment I saw it for the first time about 50 years ago.

strncpy appears somewhere around the Unix v7 time frame, however only as function in the standard C library. It is not used in the v7 kernel itself.

The code for strncpy was in the UNIX kernel since at least V6. It was eventually added to the C library under the name strncpy. Sometimes those entries were processed in userland, e.g., by fsck. The utility of strncpy is noted in the C89 rationale (FWIW I was once a member of X3J11, the C89 standards committee):

"strncpy was initially introduced into the C library to deal with fixed-length name fields in structures such as directory entries. Such fields are not used in the same way as strings: the trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter names to null assures efficient field-wise comparisons. strncpy is not by origin a "bounded strcpy," and the Committee has preferred to recognize existing practice rather than alter the function to better suit it to such use."

And I just found this comment from John Mashey (I never met John but he and I both worked under Ted Dolotta, John at Bell Labs and me at ISC in Santa Monica):

https://softwareengineering.stackexchange.com/questions/4380...

"I can answer definitively, since I wrote the originals ~1977, having moved from BTL Piscataway to Murray Hill. They were first named str*n, but were later renamed strn*, as there was some system in BTL that needed first 6 letters of external names to be unique.

I was working on kernel & user code that supported rudimentary per-process accounting, which started with someone else, but needed extensions due to big increase in UNIX systems in computer centers, who wanted more performance analysis. I.e. this was supported by commands like accton(1), acctcms(1),acctcom(1), acctmerge(1) (all in UNIX/TS 1.0, Nov 1978, which was ~Research V7 with first steps of PWB/UNIX influence. Think of that as 1.0, then PWB/UNIX 2.0, then UNIX System III...

The records described in acct(5) held the last 8 characters of the command pathname,truncated if necessary and thus possibly not null-terminated. I found multiple instances of inline code to manipulate these, which seemed a bad idea, so I wrote the str*n functions and replaced the inline code, and also used them in the various commands.

I also thought it was a good idea for better code safety.:-) Sigh."

Re: Linux eliminates the strncpy API after six years of work, 360 patches

#146
post #118

Earlier quoted context omitted.

Today yes, but 40 years ago someone made the decision that a string was a char array and that every string manipulation going forward would require manipulating arrays. Talking about costly decisions. It’s actually interesting to compare the pain and suffering of switching to a string datatype in the 80s (refactoring the limited code base then) vs the next 40 years of unnecessary boiler plate syntax and bugs for not…

Linux doesn't exist in the 1980s, Linus started this work in the 1990s. But yes, the string slice type should have existed in C89 and it's very obvious from here that not having something of this sort - maybe what Rust would call &[u8] the reference to a slice of bytes - was a big problem for C. The correct way to represent this is what's called a "fat pointer". A pair of values, one is a conventional "thin" pointer…

I'd be curious to see how much CPU time is wasted on looking for a null every time strlen is called. The extra length integer is probably insignificant compared to that.

Re: Linux eliminates the strncpy API after six years of work, 360 patches

#147

Earlier quoted context omitted.

Partly agree but there would have been squabbling on the data type of the size, unless it was variable length. The latter would have had other issues too. For a while, 16bit would probably have seemed too extravagant. Now 32bit would probably seem too small. For a “strongly typed” language, C is pretty damn loose where would have mattered.

I like the D approach where arrays are just `struct { size_t length; T* ptr; }` internally --- and strings are just arrays of `immutable(char)`. It has a big advantage over the Pascal approach in that you can do zero-copy slicing, since the length is separate from the actual data. And `size_t` makes perfect sense for the length here. If your strings are longer than the address space (which `size_t` technically isn't,…

This only makes a difference in terms of memory size, not in terms of speed, because for decades processors and compilers have been optimized for moving bytes around.

But one would note that in order to gain memory for this particular case of slicing, one introduces 2 extra words (size and pointer) for every other cases. Like perhaps the second most common string operation, concatenation. In those other cases, the benefit is slightly negative.

I've had extensive experience with "counted strings" because I implemented a bunch of Forth interpreters which also uses this scheme. Including the common trick of using counted and zero-terminated strings, which is the worst of both worlds in the end. Forth is the kind of language that quickly show you how bad your choices are.

I eventually dropped all that and adopted ASCIIZ strings because they are generally more efficient (if you pay attention to the strlen() performance pitfalls) and having a dead simple interface with the rest of the world (OS, libraries) is more valuable.

Re: Linux eliminates the strncpy API after six years of work, 360 patches

#148
post #15

Earlier quoted context omitted.

In addition to having to pick a size for the length counter and then, later, having to differentiate between lengths in bytes, codepoints, and glyphs, you can't subdivide a Pascal string using pointer arithmetic. To pass just the end of a string into a function, you have to either copy the tail of one Pascal-style string to another with a smaller size value, or your string has to be a struct with an integer and a poi…

You can have a universal variable length field, for example 2 bytes for strings The subdivision issue is a good perspective, but i would argue the performance impact of cloning substrings is dwarfed by the redundant full string reads to find length.

> You can have a universal variable length field, for example 2 bytes for strings To hold the length of a string, I'd do something similar to unicode:

7-bits for size + 1-bit for continuation, then 15 bits for size + 1 bit for continuation, then 23-bits for size + 1 bit for continuation, etc.

Or maybe even do it exactly the same as unicode:

    0XXX XXXX -> length of string is in those 7 bits
    1XXX XXXX  XXXX XXXX -> length of string is in those 7+8 bits
    11XX XXXX  XXXX XXXX  XXXX XXXX-> length of string is in those 6+8+8 bits
    ...

> On the critical short string path, it costs just a single bit test.

A few more clock cycles compared to NULL-termination, although my alternatives above require even more clock cycles.

If the hardware had instructions for sentinel values, things would be easier (Like how DOS calls used '$' termination for strings) and safer.

Load a sentinel byte into a register and have dedicated copy and compare instructions that take each two addresses (src and dst) and copies (or compares) src/dst until the terminator is reached (with copy copying the sentinel as well).

Considering that sentinel values are needed so often, and are so useful, it's surprising that this is not in any ISA. What we have now is kludgy workarounds in the HLL for this. It's hard to blame the HLL, because some workaround has to be implemented.

Re: Linux eliminates the strncpy API after six years of work, 360 patches

#149
post #138

Earlier quoted context omitted.

Clang and GCC both let you use Pascal strings in C if you would like (with `\p`). But Pascal strings aren't that useful today because the maximum length is too short.

Why would a pascal string be any shorter than a C string? A C string is one pointer reaching all of memory, a Pascal string is two pointers reaching all of memory

A Pascal string has a leading length byte. Because that is one byte, the text can't exceed 255 characters.

Re: Linux eliminates the strncpy API after six years of work, 360 patches

#150
post #88
post #85

Earlier quoted context omitted.

> Of course I get downvoted for saying this. HN isn't interested in reality any more. I suspect that rather many of us are simply just tired of Claude and friends getting shoehorned into any conversation about programming at this point. It is about as fun as the Rust Brigade entering any discussion about C. It adds nothing new to the discussion and it is frankly tiring since we pretty much at any time have a handful…

Well - except in this conversation it's incredibly relevant. It took six years to do this work when the work is likely mostly mechanical and could have been done much more quickly and safely with an automated system. I thought automation would be interesting to HN - given the context and the fact it was not used.

Right. Six years of work on a grunt job. That's what automation is for.
Post reply on HN