Re: [DNG] "Common knowledge?"-question
Steve Littwrites: > Rainer Weikusat wrote: > >> Can the effect of the following C function >> >> static void print_start(char const *name, char const *what) >> { [...] >> } >> >> be considered obvious or should it rather get an explanation? > > Hi Rainer, > > Others have pointed out potential coding problems, but I'm just going > to answer your question about need for comments. In my opinion, the > preceding function is short enough to document itself *if and only if* > the function gets a much more descriptive name. Descriptive of what it > does and how it's used. The naming is indeed poor. Thank you for pointing this out. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Am Montag, 25. Januar 2016 schrieb Rainer Weikusat: > "Dr. Nikolaus Klepp"writes: > > [...] > > > What about making the source smaller and not the executable? > > > > static void print_start(char const *name, char const *what) { > > if (name[0]) fprintf("%c%s",name[0]&~0x20, name+1); > > fprintf(stderr, " %s: ",what); > > } > > Are you seriously convinced that - in 2016 - there are still people who > haven't heard of the stdio library introduced with the 7th edition of > UNIX(*)? Well ... yes. Nik -- Please do not email me anything that you are not comfortable also sharing with the NSA. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Le 24/01/2016 19:14, KatolaZ a écrit : Soo, the above is nearly the same as > > char buf[total]; > p = buf; > >Why then use alloca()? > Maybe because char buf[total]; works only in ANSI C11. I still don't see the need for an internal buffer to print out a formatted string, to be honest:) The following works in plain old C: #include #include static void print_start(char const *name, char const *what) { unsigned name_len, what_len, total; name_len = strlen(name); what_len = strlen(what); total = name_len + what_len + 3; { char buf[total], *p=buf; memcpy(p, name, name_len); p += name_len; *p++ = ' '; memcpy(p, what, what_len); p += what_len; *p++ = ':'; *p = ' '; *buf &= ~0x20; Write(2, buf, total); } } Embedded subprograms have other use cases. In long programs, they allow to declare variables with a limited scope, just near where they are used. Didier ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Mon, Jan 25, 2016 at 09:27:15AM +0100, Didier Kryn wrote: [cut] > > The following works in plain old C: > > #include > #include > static void print_start(char const *name, char const *what) > { > unsigned name_len, what_len, total; > > name_len = strlen(name); > what_len = strlen(what); > total = name_len + what_len + 3; > { >char buf[total], *p=buf; >memcpy(p, name, name_len); >p += name_len; >*p++ = ' '; >memcpy(p, what, what_len); >p += what_len; >*p++ = ':'; >*p = ' '; >*buf &= ~0x20; > >Write(2, buf, total); > } > } > > Embedded subprograms have other use cases. In long programs, > they allow to declare variables with a limited scope, just near > where they are used. I would say that having embedded subprograms in a function is not the best thing one can do in C, but that's maybe a matter of preference :) HND KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Le 25/01/2016 11:34, KatolaZ a écrit : I would say that having embedded subprograms in a function is not the best thing one can do in C Every block is a subprogram. The block in a do loop, the conditional block in an if or while statement. The subprogram blocks are everywhere in C; they're a basic construct of the language. I don't see why plain blocks woud be bad, ie neither conditional, nor loop. And I also consider a sane practice to restrict the scope of variables as much as it makes sense. It's just that there are two features that most C programmers never learn or quickly forget: 1) blocks don't need to be conditional or loop, 2) they can contain declarations. On the contrary, the ability to declare variables outside of a block, in the middle of instructions, like in C++ is a nonsense; it is an incitation to loose programming. I personnally re-discovered this very nice features a few years ago after having used the equivalent in Ada. Didier ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Am Montag, 25. Januar 2016 schrieb KatolaZ: > On Mon, Jan 25, 2016 at 09:27:15AM +0100, Didier Kryn wrote: > > [cut] > > > > > The following works in plain old C: > > > > #include > > #include > > static void print_start(char const *name, char const *what) > > { > > unsigned name_len, what_len, total; > > > > name_len = strlen(name); > > what_len = strlen(what); > > total = name_len + what_len + 3; > > { > >char buf[total], *p=buf; > >memcpy(p, name, name_len); > >p += name_len; > >*p++ = ' '; > >memcpy(p, what, what_len); > >p += what_len; > >*p++ = ':'; > >*p = ' '; > >*buf &= ~0x20; > > > >Write(2, buf, total); > > } > > } > > > > Embedded subprograms have other use cases. In long programs, > > they allow to declare variables with a limited scope, just near > > where they are used. > > I would say that having embedded subprograms in a function is not the > best thing one can do in C, but that's maybe a matter of preference :) > > HND > > KatolaZ > What about making the source smaller and not the executable? static void print_start(char const *name, char const *what) { if (name[0]) fprintf("%c%s",name[0]&~0x20, name+1); fprintf(stderr, " %s: ",what); } I know this is not slim, but as maintenance time rises with pow(lines-of-code,something>1.0), it pays quite soon :-) -- Please do not email me anything that you are not comfortable also sharing with the NSA. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Mon, Jan 25, 2016 at 12:18:09PM +0100, Dr. Nikolaus Klepp wrote: [cut] > > What about making the source smaller and not the executable? > > static void print_start(char const *name, char const *what) { > if (name[0]) fprintf("%c%s",name[0]&~0x20, name+1); > fprintf(stderr, " %s: ",what); > } > > I know this is not slim, but as maintenance time rises with > pow(lines-of-code,something>1.0), it pays quite soon :-) +1 HND KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Didier Krynwrites: > Le 24/01/2016 19:14, KatolaZ a écrit : >>> Soo, the above is nearly the same as >>> > >>> > char buf[total]; >>> > p = buf; >>> > >>> >Why then use alloca()? >>> > >> Maybe because >> char buf[total]; >> >> works only in ANSI C11. I still don't see the need for an internal >> buffer to print out a formatted string, to be honest:) > > The following works in plain old C: > > #include > #include > static void print_start(char const *name, char const *what) > { > unsigned name_len, what_len, total; > > name_len = strlen(name); > what_len = strlen(what); > total = name_len + what_len + 3; > { >char buf[total], *p=buf; It works if the compiler supports the VLA (variable-length array) feature introduced with C99. But besides apparently aesthetically pleasing to certain people, it doesn't offer anything which alloca doesn't offer as well and doesn't offer some things the latter does, eg, allocating structures which will end up being linked together via pointers. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
"Dr. Nikolaus Klepp"writes: [...] > What about making the source smaller and not the executable? > > static void print_start(char const *name, char const *what) { > if (name[0]) fprintf("%c%s",name[0]&~0x20, name+1); > fprintf(stderr, " %s: ",what); > } Are you seriously convinced that - in 2016 - there are still people who haven't heard of the stdio library introduced with the 7th edition of UNIX(*)? ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Peter Olsonwrites: >> On January 23, 2016 at 1:36 PM Rainer Weikusat >> wrote: >> >> Peter Olson writes: >> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat >> wrote: >> >> [...] >> >> >> p = buf = alloca(total); >> >> [...] >> >> > the failure mode of alloca is SIGSEGV or some other malfunction and >> > there is no way to test for it >> >> It's supposed to allocate memory in the current stack frame which will >> work unless the stack has already grown to the limit. > >>From man7.org/linux/man-pages/man3/alloca.3.html section BUGS: >There is no error indication if the stack frame cannot be extended. >(However, after a failed allocation, the program is likely to receive >a SIGSEGV signal if it attempts to access the unallocated >space.) Calling this a bug is technical nonsense: The way stack allocation works for a single-threaded process on UNIX(*) etc is that the code just uses whatever it needs and that the kernel's supposed to handle faults resulting from accessing a not-yet-valid address by making it available. In this respect, there's no difference between alloca and static stack allocations. If a program tries to use more stack space than can be provided, it may end up getting a SIGSEGV. Or it may silently overwrite memory used for something different. In either case, the code cannot possibly work in the it was written. OTOH, space allocated on the stack will be automatically reclaimed after the corresponding function returned which is the best 'automatic memory management' one can get in C. It's also good for locality as different functions called at the same depth will keep using the same memory area. > I have never been a fan of alloca though it obviously _can_ be used safely > with > a little care. Do you realize that Linux uses 8K kernel stacks (and can be configured to use 4K) with no protection against overwriting whatsoever? In contrast to this, even on the 32 bit system, the userspace stack area is practically infinite compared to the memory requirements of small program and this becomes even more true on 64bit systems. With some amount criminal energy, it's possible to use the stack 'unsafely'. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Didier Krynwrites: > Le 23/01/2016 19:28, Rainer Weikusat a écrit : >> Didier Kryn writes: >>> Le 23/01/2016 12:16, Didier Kryn a écrit : I'm curious of the reason why you specify static void print_start(char const *name, char const *what) [...] >>> Sorry, I overlooked the code and read "char const *name" as if it >>> was "char * const name". Actually the syntax you used is equivalent to >>> "const char *name". >> That's a habit based on an observation I made when I started to write >> code in C: Type qualifiers are left-associative (presumably a misuse of >> the term) unless there's nothing to the left of them, [...] > So, we could express it as the general declaration would be: [...] > But another syntax is allowed, where the qualifier[s] can be on > the left. I'm not sure there's a BNF description of the C syntax. It's really declaration: declaration-specifiers init-declarator-list[opt] ; declaration-specifiers: storage-class-specifier declaration-specifiers[opt] type-specifier declaration-specifiers[opt] type-qualifier declaration-specifiers[opt] function-specifier declaration-specifiers[opt] Which means a type-qualifier can appear both to the left and to the right of a type specifier. Originally (as I wrote) the fact that const char * meant 'pointer to constant char' while char const * also meant this and 'constant pointer to char' had to be expressed as char * const simply annoyed me because of it's irregularity --- but now, after having had to deal with a somewhat largish Java codebase where absolutely everything had a final tacked onto it, thereby making it seriously difficult to spot the acting code among all the pointless declarational clutter, I'm presumably in the process of stopping to use const altogether. >>> It actually protects the string from being overwritten by the >>> function. >> Not really. It just asserts that the string won't be modified using this >> pointer. In theory, this would enable a compiler to optimize such >> accesses, eg, collapse many of them into one, however, in practice, gcc >> doesn't do that, and the qualifier is useless. > > The most important goal is not to optimise the executable, it is > to protect against programmer's errors. gcc will warn you if you try > to modify a constant. It won't even compile code trying to use a pointer-to-constant-something to modify something. But this usually just means that the const ought to be dropped. C is all about managing memory manually and this means whenever the content of some (set of) memory location(s) is to be modified, thought must be put into determining where this memory comes from and which other code might use it in which way. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
k...@aspodata.se writes: > Katola2: > ... >> void another_print_start(char *name, char *what){ >> >> char c[3] = " :"; >> >> c[2] = name[0] & ~0x20; >> >> write(2, c+2, 1); >> write(2, name+1, strlen(name) -1); >> write(2, c, 2); >> write(2, what, strlen(what)); >> >> } > > Why not just use writev(2) and write it one system call ? The idea behind writev is to avoid userspace block memory copies prior to doing a system call which will end up copying all the memory contents into kernel memory. In order to achieve this, a vector of struct iovec structures each specifiyng the location and size of a single area is used. A struct iovec is struct iovec { void *iov_base; size_t iov_len; }; On a 64-bit system, this means that an additional 16 bytes of data need to be copied by the kernel for every area used by writev. For this to be worthwhile, the average size of an area should be more than 33 bytes, otherwise, writev will end up doing more copying than userspace code had need to create a continuous area before doing the system call. And then, there's also the userspace code needed to initialize the vector. For the example above, this would be iovs->iov_base = c + 2; iovs->iov_len = 2; iovs[1].iov_base = name + 1; iovs[1].iov_len = strlen(name) - 1; iovs[2].iov_base = c; iovs[2].iov_len = 2; iovs[3].iov_base = what; iovs[3].iov_len = strlen(what); compared to name_len = strlen(name); what_len = strlen(what); total = name_len + what_len + 3; p = buf = alloca(total); memcpy(p, name, name_len); p += name_len; *p++ = ' '; memcpy(p, what, what_len); p += what_len; *p++ = ':'; *p = ' '; that's 3 lines of code less which is "not great". In addition to this, both write and writev may end up writing less data than requested and the code for restarting a partially completed writev is more complicated than the same for write. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Reiner Weikusat: > Peter Olsonwrites: > > >> On January 23, 2016 at 1:36 PM Rainer Weikusat > >> wrote: > >> > >> Peter Olson writes: > >> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat > >> wrote: > >> > >> [...] > >> > >> >> p = buf = alloca(total); > >> > >> [...] > >> > >> > the failure mode of alloca is SIGSEGV or some other malfunction and > >> > there is no way to test for it You should be able to cache a SIGSEGV if you are useing sigaltstack(). Never tested it though and don't know it it is useful at all. ... > In this respect, there's no difference between alloca and static stack > allocations. ... Soo, the above is nearly the same as char buf[total]; p = buf; Why then use alloca()? Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Rainer Weikusat: > k...@aspodata.se writes: > > Katola2: > > ... > >> void another_print_start(char *name, char *what){ > >> > >> char c[3] = " :"; > >> > >> c[2] = name[0] & ~0x20; > >> > >> write(2, c+2, 1); > >> write(2, name+1, strlen(name) -1); > >> write(2, c, 2); > >> write(2, what, strlen(what)); > >> > >> } > > > > Why not just use writev(2) and write it one system call ? Since people complained about allocations, I thought you could use this and have a static struct iovec[4];, then the only allocations done would be for simple types. > The idea behind writev is to avoid userspace block memory copies prior ... > that's 3 lines of code less which is "not great". In addition to this, > both write and writev may end up writing less data than requested and > the code for restarting a partially completed writev is more complicated > than the same for write. Both true. Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Sun, Jan 24, 2016 at 05:25:47PM +0100, k...@aspodata.se wrote: [cut] > ... > > In this respect, there's no difference between alloca and static stack > > allocations. > ... > > Soo, the above is nearly the same as > > char buf[total]; > p = buf; > > Why then use alloca()? > Maybe because char buf[total]; works only in ANSI C11. I still don't see the need for an internal buffer to print out a formatted string, to be honest :) HND KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
"Dr. Nikolaus Klepp"writes: > Am Freitag, 22. Januar 2016 schrieb Rainer Weikusat: [...] >> name_len = strlen(name); >> what_len = strlen(what); >> total = name_len + what_len + 3; >> >> p = buf = alloca(total); >> memcpy(p, name, name_len); >> p += name_len; >> *p++ = ' '; >> memcpy(p, what, what_len); >> p += what_len; >> *p++ = ':'; [...] > just out of couriosity: why don't you use "strcat"? Because strcat is A Seriously Bizarre Invention[tm]. Programmers using the strcat or wcscat function (or the following strncat or wcsncar functions for that matter) can easily be recognized as lazy and reckless. In almost all situations the lengths of the participating strings are known (it better should be since how can one otherwise ensure the allocated size of the buffer is sufficient?) Or at least, one could know them if one keeps track of the results of the various function calls. But then it is very inefficient to use strcat/wcscat. A lot of time is wasted finding the end of the destination string so that the actual copying can start. https://www.gnu.org/software/libc/manual/html_node/Copying-and-Concatenation.html#Copying-and-Concatenation ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
k...@aspodata.se writes: > Reiner Weikusat: >> Peter Olsonwrites: >> >> >> On January 23, 2016 at 1:36 PM Rainer Weikusat >> >> wrote: >> >> >> >> Peter Olson writes: >> >> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat >> >> wrote: >> >> >> >> [...] >> >> >> >> >> p = buf = alloca(total); >> >> >> >> [...] >> >> >> >> > the failure mode of alloca is SIGSEGV or some other malfunction and >> >> > there is no way to test for it > > You should be able to cache a SIGSEGV if you are useing sigaltstack(). > Never tested it though and don't know it it is useful at all. > > ... >> In this respect, there's no difference between alloca and static stack >> allocations. > ... > > Soo, the above is nearly the same as > > char buf[total]; > p = buf; > > Why then use alloca()? This obviously cuts both ways: Considering that C99 style variable arrays share all the (largely hypothetical) drawbacks of alloca but offer less features, why use them? ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
k...@aspodata.se writes: > Reiner Weikusat: >> Peter Olsonwrites: >> >> >> On January 23, 2016 at 1:36 PM Rainer Weikusat >> >> wrote: >> >> >> >> Peter Olson writes: >> >> 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat >> >> wrote: >> >> >> >> [...] >> >> >> >> >> p = buf = alloca(total); >> >> >> >> [...] >> >> >> >> > the failure mode of alloca is SIGSEGV or some other malfunction and >> >> > there is no way to test for it > > You should be able to cache a SIGSEGV if you are useing sigaltstack(). > Never tested it though and don't know it it is useful at all. > > ... >> In this respect, there's no difference between alloca and static stack >> allocations. > ... > > Soo, the above is nearly the same as > > char buf[total]; > p = buf; > > Why then use alloca()? This obviously cuts both ways: Considering that C99 style variable arrays share all the (largely hypothetical) drawbacks of alloca but offer less features, why use them? ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
k...@aspodata.se writes: > Rainer Weikusat: >> k...@aspodata.se writes: >> > Katola2: >> > ... >> >> void another_print_start(char *name, char *what){ >> >> >> >> char c[3] = " :"; >> >> >> >> c[2] = name[0] & ~0x20; >> >> >> >> write(2, c+2, 1); >> >> write(2, name+1, strlen(name) -1); >> >> write(2, c, 2); >> >> write(2, what, strlen(what)); >> >> >> >> } >> > >> > Why not just use writev(2) and write it one system call ? > > Since people complained about allocations, I thought you could use this > and have a static struct iovec[4];, then the only allocations done > would be for simple types. > >> The idea behind writev is to avoid userspace block memory copies >> prior [and unless the average block size is more than 2 times 16, this ends up doing more copying instead of less] > ... >> that's 3 lines of code less which is "not great". In addition to this, >> both write and writev may end up writing less data than requested and >> the code for restarting a partially completed writev is more complicated >> than the same for write. > > Both true. The core of my statement was not about neligible code savings in one place ending up as code increases in another but about causing additional copying instead of avoiding it in case of small areas. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Sat, Jan 23, 2016 at 02:10:46AM -0500, Peter Olson wrote: [cut] > > I'm unhappy for two reasons: > > the failure mode of alloca is SIGSEGV or some other malfunction and there is > no way to test for it > > the *buf &= ~0x20; breaks for UTF8 strings. > > Nevermind that the function implicitly references stderr except when it > doesn't. > On a closer look, the major problem I see here is not that *buf &= ~0x20 breaks UTF8, but instead that alloca(3) allocates space on the stack frame of the caller, and could potentially cause a stack-overflow... This would pass unobserved to most eyes. I have also checked that the implementation of alloca(3) in glibc does never return a null-pointer upon failure, thus making very possible to stack-overflow. Nice example :) HND KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Le 22/01/2016 22:34, Rainer Weikusat a écrit : Can the effect of the following C function static void print_start(char const *name, char const *what) { char *buf, *p; unsigned name_len, what_len, total; name_len = strlen(name); what_len = strlen(what); total = name_len + what_len + 3; p = buf = alloca(total); memcpy(p, name, name_len); p += name_len; *p++ = ' '; memcpy(p, what, what_len); p += what_len; *p++ = ':'; *p = ' '; *buf &= ~0x20; Write(2, buf, total); } be considered obvious or should it rather get an explanation? An ASCII lowercase letter can be turned into the corresponding uppercase letter by clearing the sixth bit. toupper() wouild be better unless you can assert the first char is a lertter. I'm curious of the reason why you specify static void print_start(char const *name, char const *what) This means the pointers to the arrays of characters are constant (not the characters). The effect of this cannot be to protect the pointers in the caller program since they are passed by value -- copied into register or stack before passing control to the function. If it is for the sanity of the function itself, then congratulations, this is a sane thing to do, even if it is easy to check by eye that the pointers aren't modified. But, to be consistent, since your function doesn't even modify the content of the strings, you should also declare constant the characters themself, like in the following: static void print_start(const char const *name, const char const *what) Didier ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Le 23/01/2016 14:48, Hendrik Boom a écrit : I've always said the C syntax for declarators was confusing. Even those who understand it read it wrong! (Yes, In understand the logic behind it. It is still confusing.) I fully agree: it's confusing. Actually, in a single statement one can declare objects of different data types, the base type, pointers to it, pointers to pointers etc. This allows for many places to put qualifiers such as const, volatile, static, register. The syntax used by Rainer is usefull when declaring in the same statement constant and non-constant characters, which I, personnaly, try to avoid because it is confusing. Confusing statements simply boost the probability for bugs. Didier ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Fri, 22 Jan 2016 21:34:28 + Rainer Weikusatwrote: > Can the effect of the following C function > > static void print_start(char const *name, char const *what) > { > char *buf, *p; > unsigned name_len, what_len, total; > > name_len = strlen(name); > what_len = strlen(what); > total = name_len + what_len + 3; > > p = buf = alloca(total); > memcpy(p, name, name_len); > p += name_len; > *p++ = ' '; > memcpy(p, what, what_len); > p += what_len; > *p++ = ':'; > *p = ' '; > > *buf &= ~0x20; > > Write(2, buf, total); > } > > be considered obvious or should it rather get an explanation? Hi Rainer, Others have pointed out potential coding problems, but I'm just going to answer your question about need for comments. In my opinion, the preceding function is short enough to document itself *if and only if* the function gets a much more descriptive name. Descriptive of what it does and how it's used. print_start() means nothing to me. Is "start" a noun (the start of the record) or a verb (start the printing). And the print isn't to a printer, it's to stdout, so a better word would be "output". But even those aren't sufficient: This thing is concatenating two strings, adding punctuation, and capitalizing the first character. Why are all these things necessary? If the function name can address that, perhaps it can be self documenting. Otherwise, there's no shame in putting a few lines of comments above the function, and personally I'd put an inline comment on that *buf &= ~0x20; trick. Or you could make a macro called upcase_first_letter() that does that. That makes it self-documenting, and yet because it's a macro it compiles as if it were inline. SteveT Steve Litt January 2016 featured book: Twenty Eight Tales of Troubleshooting http://www.troubleshooters.com/28 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Sat, Jan 23, 2016 at 11:45:30AM -0500, Steve Litt wrote: > On Fri, 22 Jan 2016 21:34:28 + > Rainer Weikusatwrote: > > > Can the effect of the following C function > > > > static void print_start(char const *name, char const *what) > > { > > char *buf, *p; > > unsigned name_len, what_len, total; > > > > name_len = strlen(name); > > what_len = strlen(what); > > total = name_len + what_len + 3; > > > > p = buf = alloca(total); > > memcpy(p, name, name_len); > > p += name_len; > > *p++ = ' '; > > memcpy(p, what, what_len); > > p += what_len; > > *p++ = ':'; > > *p = ' '; > > > > *buf &= ~0x20; > > > > Write(2, buf, total); > > } > > > > be considered obvious or should it rather get an explanation? > > Hi Rainer, > > Others have pointed out potential coding problems, but I'm just going > to answer your question about need for comments. In my opinion, the > preceding function is short enough to document itself *if and only if* > the function gets a much more descriptive name. Descriptive of what it > does and how it's used. > > print_start() means nothing to me. Is "start" a noun (the start of the > record) or a verb (start the printing). And the print isn't to a > printer, it's to stdout, so a better word would be "output". But even > those aren't sufficient: This thing is concatenating two strings, > adding punctuation, and capitalizing the first character. Why are all > these things necessary? If the function name can address that, perhaps > it can be self documenting. > > Otherwise, there's no shame in putting a few lines of comments above > the function, and personally I'd put an inline comment on that *buf &= > ~0x20; trick. Or you could make a macro called upcase_first_letter() > that does that. That makes it self-documenting, and yet because it's a > macro it compiles as if it were inline. A good compiler would inline it even if you write it as a funciton, because it's not recursive, and its code is probably smaller than that of a function call. The trouble with macros in C is that they do not respect nested scopes. (This is a criticism of the language, not of coding style.) -- hendrik k ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Didier Krynwrites: > Le 23/01/2016 12:16, Didier Kryn a écrit : >> >> I'm curious of the reason why you specify >>static void print_start(char const *name, char const *what) >> >> This means the pointers to the arrays of characters are constant >> (not the characters). [...] > Sorry, I overlooked the code and read "char const *name" as if it > was "char * const name". Actually the syntax you used is equivalent to > "const char *name". That's a habit based on an observation I made when I started to write code in C: Type qualifiers are left-associative (presumably a misuse of the term) unless there's nothing to the left of them, eg const char *s; declares a pointer to a constant string, char const *s; does the same and char * const s; declares a constant pointer to a non-constant string. If the qualifier is aways to the right of the thing it's supposed to qualify, it uniformly binds to what's left of it. [...] > It actually protects the string from being overwritten by the > function. Not really. It just asserts that the string won't be modified using this pointer. In theory, this would enable a compiler to optimize such accesses, eg, collapse many of them into one, however, in practice, gcc doesn't do that, and the qualifier is useless. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Sat, Jan 23, 2016 at 06:59:10PM +0100, Didier Kryn wrote: [cut] > > The syntax used by Rainer is usefull when declaring in the same > statement constant and non-constant characters, which I, personnaly, > try to avoid because it is confusing. Confusing statements simply > boost the probability for bugs. > Correct, but in that specific case the potential bug is in the use of alloca, not the declarations... :) HND KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Sat, Jan 23, 2016 at 06:36:46PM +, Rainer Weikusat wrote: > Peter Olsonwrites: > 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat > wrote: > > [...] > > >> p = buf = alloca(total); > > [...] > > > the failure mode of alloca is SIGSEGV or some other malfunction and > > there is no way to test for it > > It's supposed to allocate memory in the current stack frame which will > work unless the stack has already grown to the limit. Since the size of alloca is determined by the user, not by the developer of the function, you should assume that the call to alloca is a potential source of attacks based on stack overflow, or of very-hard-to-reproduce SIGSEGVs. Also, in this specific case there is no need at all to copy the two input strings in an internal buffer. The following function will do exactly the same: void another_print_start(char *name, char *what){ char c[3] = " :"; c[2] = name[0] & ~0x20; write(2, c+2, 1); write(2, name+1, strlen(name) -1); write(2, c, 2); write(2, what, strlen(what)); } It's just a little more cryptic (and I admit that reusing the last byte of c[] is not best-practices), but avoids a call to alloca(3) (which is anyway deprecated) with minimal space overhead, and the problem of managing internal buffers otherwise. I assumed that you had to use write(2) instead of fprintf(3), for whatever reason, even if I can't see why this should be the case, since if you have alloca(3) then you should most probably also have fprintf(3), whatever the implementation of the C library My2Cents KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Sat, Jan 23, 2016 at 04:45:05PM +0100, Didier Kryn wrote: > Le 23/01/2016 12:16, Didier Kryn a écrit : > > > >I'm curious of the reason why you specify > > static void print_start(char const *name, char const *what) > > > >This means the pointers to the arrays of characters are > >constant (not the characters). The effect of this cannot be to > >protect the pointers in the caller program since they are passed > >by value -- copied into register or stack before passing control > >to the function. If it is for the sanity of the function itself, > >then congratulations, this is a sane thing to do, even if it is > >easy to check by eye that the pointers aren't modified. But, to be > >consistent, since your function doesn't even modify the content of > >the strings, you should also declare constant the characters > >themself, like in the following: > >static void print_start(const char const *name, const char > >const *what) > > Sorry, I overlooked the code and read "char const *name" as if > it was "char * const name". Actually the syntax you used is > equivalent to "const char *name". It actually protects the string > from being overwritten by the function. I've always said the C syntax for declarators was confusing. Even those who understand it read it wrong! (Yes, In understand the logic behind it. It is still confusing.) -- hendrik ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Le 23/01/2016 12:16, Didier Kryn a écrit : I'm curious of the reason why you specify static void print_start(char const *name, char const *what) This means the pointers to the arrays of characters are constant (not the characters). The effect of this cannot be to protect the pointers in the caller program since they are passed by value -- copied into register or stack before passing control to the function. If it is for the sanity of the function itself, then congratulations, this is a sane thing to do, even if it is easy to check by eye that the pointers aren't modified. But, to be consistent, since your function doesn't even modify the content of the strings, you should also declare constant the characters themself, like in the following: static void print_start(const char const *name, const char const *what) Sorry, I overlooked the code and read "char const *name" as if it was "char * const name". Actually the syntax you used is equivalent to "const char *name". It actually protects the string from being overwritten by the function. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Katola2: ... > void another_print_start(char *name, char *what){ > > char c[3] = " :"; > > c[2] = name[0] & ~0x20; > > write(2, c+2, 1); > write(2, name+1, strlen(name) -1); > write(2, c, 2); > write(2, what, strlen(what)); > > } Why not just use writev(2) and write it one system call ? Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Peter Olsonwrites: 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat wrote: [...] >> p = buf = alloca(total); [...] > the failure mode of alloca is SIGSEGV or some other malfunction and > there is no way to test for it It's supposed to allocate memory in the current stack frame which will work unless the stack has already grown to the limit. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
> On January 23, 2016 at 1:36 PM Rainer Weikusat >wrote: > > Peter Olson writes: > 5>> On January 22, 2016 at 4:34 PM Rainer Weikusat > wrote: > > [...] > > >> p = buf = alloca(total); > > [...] > > > the failure mode of alloca is SIGSEGV or some other malfunction and > > there is no way to test for it > > It's supposed to allocate memory in the current stack frame which will > work unless the stack has already grown to the limit. From man7.org/linux/man-pages/man3/alloca.3.html section BUGS: There is no error indication if the stack frame cannot be extended. (However, after a failed allocation, the program is likely to receive a SIGSEGV signal if it attempts to access the unallocated space.) I have never been a fan of alloca though it obviously _can_ be used safely with a little care. The hazard of passing a very long string by accident is what makes it unsafe. In this case, with short enough strings it is no more hazardous than a recursion that is too deep. Peter Olson ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Le 23/01/2016 19:28, Rainer Weikusat a écrit : Didier Krynwrites: Le 23/01/2016 12:16, Didier Kryn a écrit : I'm curious of the reason why you specify static void print_start(char const *name, char const *what) This means the pointers to the arrays of characters are constant (not the characters). [...] Sorry, I overlooked the code and read "char const *name" as if it was "char * const name". Actually the syntax you used is equivalent to "const char *name". That's a habit based on an observation I made when I started to write code in C: Type qualifiers are left-associative (presumably a misuse of the term) unless there's nothing to the left of them, eg const char *s; declares a pointer to a constant string, char const *s; does the same and char * const s; declares a constant pointer to a non-constant string. If the qualifier is aways to the right of the thing it's supposed to qualify, it uniformly binds to what's left of it. [...] So, we could express it as the general declaration would be: = ; = | , = = | To simplify the description, I assume can be null. For example: char x, * const *p; where p would be a pointer to a constant pointer to a char. But another syntax is allowed, where the qualifier[s] can be on the left. I'm not sure there's a BNF description of the C syntax. It actually protects the string from being overwritten by the function. Not really. It just asserts that the string won't be modified using this pointer. In theory, this would enable a compiler to optimize such accesses, eg, collapse many of them into one, however, in practice, gcc doesn't do that, and the qualifier is useless. The most important goal is not to optimise the executable, it is to protect against programmer's errors. gcc will warn you if you try to modify a constant. Didier ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Fri, Jan 22, 2016 at 09:34:28PM +, Rainer Weikusat wrote: > Can the effect of the following C function > > static void print_start(char const *name, char const *what) > { [cut] > be considered obvious or should it rather get an explanation? > katolaZ said: Well, it will depend on the audience. It's a pretty basic example and if one has got some expeience of writing C code would get it at the first read (even without your explanation at the end, I guess). If the audience is a freshman module in programming, I wouldn't use it as a first example ;) KatolaZ said -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
Am Freitag, 22. Januar 2016 schrieb Rainer Weikusat: > Can the effect of the following C function > > static void print_start(char const *name, char const *what) > { > char *buf, *p; > unsigned name_len, what_len, total; > > name_len = strlen(name); > what_len = strlen(what); > total = name_len + what_len + 3; > > p = buf = alloca(total); > memcpy(p, name, name_len); > p += name_len; > *p++ = ' '; > memcpy(p, what, what_len); > p += what_len; > *p++ = ':'; > *p = ' '; > > *buf &= ~0x20; > > Write(2, buf, total); > } > > be considered obvious or should it rather get an explanation? just out of couriosity: why don't you use "strcat"? -- Please do not email me anything that you are not comfortable also sharing with the NSA. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
> On January 22, 2016 at 4:34 PM Rainer Weikusat >wrote: > > Can the effect of the following C function > > static void print_start(char const *name, char const *what) > { > char *buf, *p; > unsigned name_len, what_len, total; > > name_len = strlen(name); > what_len = strlen(what); > total = name_len + what_len + 3; > > p = buf = alloca(total); > memcpy(p, name, name_len); > p += name_len; > *p++ = ' '; > memcpy(p, what, what_len); > p += what_len; > *p++ = ':'; > *p = ' '; > > *buf &= ~0x20; > > Write(2, buf, total); > } > > be considered obvious or should it rather get an explanation? > > An ASCII lowercase letter can be turned into the corresponding uppercase > letter by clearing the sixth bit. I'm unhappy for two reasons: the failure mode of alloca is SIGSEGV or some other malfunction and there is no way to test for it the *buf &= ~0x20; breaks for UTF8 strings. Nevermind that the function implicitly references stderr except when it doesn't. Peter Olson ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] "Common knowledge?"-question
On Fri, Jan 22, 2016 at 09:34:28PM +, Rainer Weikusat wrote: > Can the effect of the following C function > > static void print_start(char const *name, char const *what) > { > char *buf, *p; > unsigned name_len, what_len, total; > > name_len = strlen(name); > what_len = strlen(what); > total = name_len + what_len + 3; > > p = buf = alloca(total); > memcpy(p, name, name_len); > p += name_len; > *p++ = ' '; > memcpy(p, what, what_len); > p += what_len; > *p++ = ':'; > *p = ' '; > > *buf &= ~0x20; > > Write(2, buf, total); > } > > be considered obvious or should it rather get an explanation? > > An ASCII lowercase letter can be turned into the corresponding uppercase > letter by clearing the sixth bit. > ___ My answer is that you shouldn't assume someone will understand what your function does, even if you think a five-year-old should get it. It's always a good idea to include a comment block at the top of your function describing what it does, what variables it expects, and what it does (or in this case) doesn't return. Yes, that means explicitly state a void function returns no value. If nothing else, you do someone else the courtesy of saving them time by explaining what your function does so they don't need to read through it to figure that out. If they want to read through it anyway, they still have that option of course. Just my $0.01 worth. Greg -- web site: http://www.gregn.net gpg public key: http://www.gregn.net/pubkey.asc skype: gregn1 (authorization required, add me to your contacts list first) If we haven't been in touch before, e-mail me before adding me to your contacts. -- Free domains: http://www.eu.org/ or mail dns-mana...@eu.org ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng