Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #163436 > unrolled thread
| Started by | pozz <pozzugno@gmail.com> |
|---|---|
| First post | 2021-11-17 11:36 +0100 |
| Last post | 2021-11-20 20:49 -0800 |
| Articles | 20 on this page of 48 — 16 participants |
Back to article view | Back to comp.lang.c
Automatic strings without malloc pozz <pozzugno@gmail.com> - 2021-11-17 11:36 +0100
Re: Automatic strings without malloc pozz <pozzugno@gmail.com> - 2021-11-17 11:38 +0100
Re: Automatic strings without malloc Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2021-11-17 03:00 -0800
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-17 12:04 +0100
Re: Automatic strings without malloc Manfred <noname@add.invalid> - 2021-11-17 18:19 +0100
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-17 20:34 +0100
Re: Automatic strings without malloc pozz <pozzugno@gmail.com> - 2021-11-18 10:07 +0100
Re: Automatic strings without malloc Thiago Adams <thiago.adams@gmail.com> - 2021-11-17 05:11 -0800
Re: Automatic strings without malloc Philipp Klaus Krause <pkk@spth.de> - 2021-11-18 15:29 +0100
Re: Automatic strings without malloc Bart <bc@freeuk.com> - 2021-11-17 13:47 +0000
Re: Automatic strings without malloc scott@slp53.sl.home (Scott Lurndal) - 2021-11-17 15:34 +0000
Re: Automatic strings without malloc Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2021-11-17 07:36 -0800
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-17 16:56 +0100
Re: Automatic strings without malloc scott@slp53.sl.home (Scott Lurndal) - 2021-11-17 18:21 +0000
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-17 20:37 +0100
Re: Automatic strings without malloc scott@slp53.sl.home (Scott Lurndal) - 2021-11-17 21:35 +0000
Re: Automatic strings without malloc Thiago Adams <thiago.adams@gmail.com> - 2021-11-19 05:38 -0800
Re: Automatic strings without malloc Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2021-11-19 07:13 -0800
Re: Automatic strings without malloc William Ahern <william@25thandClement.com> - 2021-11-17 20:46 -0800
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-18 10:50 +0100
Re: Automatic strings without malloc Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2021-11-18 03:56 -0800
Re: Automatic strings without malloc Thiago Adams <thiago.adams@gmail.com> - 2021-11-18 05:54 -0800
Re: Automatic strings without malloc Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-11-18 16:38 +0000
Re: Automatic strings without malloc Thiago Adams <thiago.adams@gmail.com> - 2021-11-18 10:52 -0800
Re: Automatic strings without malloc Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-11-18 11:27 -0800
Re: Automatic strings without malloc Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-11-18 20:41 +0000
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-18 16:05 +0100
Re: Automatic strings without malloc Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-11-17 11:22 -0800
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-17 20:39 +0100
Re: Automatic strings without malloc Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-11-17 15:18 -0800
[OT] Generally... [Was: Automatic strings without malloc] Jeremy Brubaker <jbrubake@orionarts.invalid> - 2021-11-18 17:46 +0000
Re: [OT] Generally... [Was: Automatic strings without malloc] Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-11-18 11:21 -0800
Re: Automatic strings without malloc Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-11-17 11:14 -0800
Re: Automatic strings without malloc pozz <pozzugno@gmail.com> - 2021-11-18 10:08 +0100
Re: Automatic strings without malloc Siri Cruise <chine.bleu@yahoo.com> - 2021-11-18 12:25 -0800
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-18 23:19 +0100
Re: Automatic strings without malloc Siri Cruise <chine.bleu@yahoo.com> - 2021-11-18 17:22 -0800
Re: Automatic strings without malloc Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2021-11-19 01:46 -0800
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-19 17:29 +0100
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-19 17:26 +0100
Re: Automatic strings without malloc Siri Cruise <chine.bleu@yahoo.com> - 2021-11-19 09:00 -0800
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-19 18:25 +0100
Re: Automatic strings without malloc "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-11-19 14:58 -0800
Re: Automatic strings without malloc Guillaume <message@bottle.org> - 2021-11-19 19:37 +0100
Re: Automatic strings without malloc "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-11-19 12:34 -0800
Re: Automatic strings without malloc Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2021-11-19 13:44 -0800
Re: Automatic strings without malloc David Brown <david.brown@hesbynett.no> - 2021-11-20 13:30 +0100
Re: Automatic strings without malloc luser droog <luser.droog@gmail.com> - 2021-11-20 20:49 -0800
Page 1 of 3 [1] 2 3 Next page →
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2021-11-17 11:36 +0100 |
| Subject | Automatic strings without malloc |
| Message-ID | <sn2lvp$sl7$1@dont-email.me> |
Many times I need to construct a string through a call to sprintf and pass it to an external function. char s[32]; sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); lcd_write(s); The size of s is fixed and calculated for the maximum length of yourname, that is 9. Later in time, I need to change the message into: sprintf(s, "Hello %s, today is %d/%d/%d", yourname, day, month, year); Of course, I need to re-calculate the worst-case length, that should be now 35. However this is error-prone and I could forget to change the size of array. Is there a better way to manage this situation? I can't use malloc() because I'm on an embedded system where I can't use heap. I'm thinking to use sprintf(NULL, ...), such as: const char fmt[] = "Hi %s, today is %d/%d/%d"; size_t n = sprintf(NULL, fmt, yourname, day, month, year); char s[n + 1]; sprintf(s, fmt, yourname, day, month, year); lcd_write(s);
[toc] | [next] | [standalone]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2021-11-17 11:38 +0100 |
| Message-ID | <sn2m28$sl7$2@dont-email.me> |
| In reply to | #163436 |
Il 17/11/2021 11:36, pozz ha scritto: > Many times I need to construct a string through a call to sprintf and > pass it to an external function. > > char s[32]; > sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); > lcd_write(s); > > The size of s is fixed and calculated for the maximum length of > yourname, that is 9. > > Later in time, I need to change the message into: > > sprintf(s, "Hello %s, today is %d/%d/%d", yourname, day, month, year); > > Of course, I need to re-calculate the worst-case length, that should be > now 35. However this is error-prone and I could forget to change the > size of array. > > Is there a better way to manage this situation? I can't use malloc() > because I'm on an embedded system where I can't use heap. > > I'm thinking to use sprintf(NULL, ...), such as: I'm sorry, I mean: snprintf(NULL, 0, ...)
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2021-11-17 03:00 -0800 |
| Message-ID | <e44ba99b-496e-4b83-bc81-1e16b18639d1n@googlegroups.com> |
| In reply to | #163436 |
On Wednesday, 17 November 2021 at 10:36:53 UTC, pozz wrote: > Many times I need to construct a string through a call to sprintf and > pass it to an external function. > > char s[32]; > sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); > lcd_write(s); > > The size of s is fixed and calculated for the maximum length of > yourname, that is 9. > > Later in time, I need to change the message into: > > sprintf(s, "Hello %s, today is %d/%d/%d", yourname, day, month, year); > > Of course, I need to re-calculate the worst-case length, that should be > now 35. However this is error-prone and I could forget to change the > size of array. > > Is there a better way to manage this situation? I can't use malloc() > because I'm on an embedded system where I can't use heap. > > I'm thinking to use sprintf(NULL, ...), such as: > > const char fmt[] = "Hi %s, today is %d/%d/%d"; > size_t n = sprintf(NULL, fmt, yourname, day, month, year); > char s[n + 1]; > sprintf(s, fmt, yourname, day, month, year); > lcd_write(s); > That's a reasonable solution, as long as you know you have enough stack (and a C99 compiler). You've got to ask how likely it is that a bug whereby you overrun the buffer will persist. If a bug will be caught in the first informal test, then it's not dangerous. If it could slip through until a late stage, it's more worrying. Since a buffer overrun will corrupt the variable immediately after the buffer in memory, this might be detected immediately, or it might not be detected for some time, depending on what that variable is used for. So a dangerous bug, unless you've got some memory-checking software that can detect such situations. That's your best answer, however the software might be very expensive, or might not be available at all.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-11-17 12:04 +0100 |
| Message-ID | <sn2nk2$7mp$1@dont-email.me> |
| In reply to | #163436 |
On 17/11/2021 11:36, pozz wrote: > Many times I need to construct a string through a call to sprintf and > pass it to an external function. > > char s[32]; > sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); > lcd_write(s); > > The size of s is fixed and calculated for the maximum length of > yourname, that is 9. > > Later in time, I need to change the message into: > > sprintf(s, "Hello %s, today is %d/%d/%d", yourname, day, month, year); > > Of course, I need to re-calculate the worst-case length, that should be > now 35. However this is error-prone and I could forget to change the > size of array. > > Is there a better way to manage this situation? I can't use malloc() > because I'm on an embedded system where I can't use heap. > > I'm thinking to use sprintf(NULL, ...), such as: > > const char fmt[] = "Hi %s, today is %d/%d/%d"; > size_t n = sprintf(NULL, fmt, yourname, day, month, year); > char s[n + 1]; > sprintf(s, fmt, yourname, day, month, year); > lcd_write(s); > That would work (with your follow-up correction). You might want to put a limit on "n" to avoid accidental stack overflow. This arrangement does mean that you are doing the printf part twice. Very often in small systems you know there is a maximum size - if your screen is 40 characters wide, then 40 characters is enough in your array. And if you might need up to 40 characters then you might as well use all of the 40 chars, even though your string might be shorter - you really don't want to test your code for the name "Al" on date 1/2/2021 and then find you have a stack overflow on 10/10/2021 with the name "Rhoshandiatellyneshiaunneveshenk". (Apparently that's a real name - according to google!) It is also worth noting that only one task should be calling lcd_write at a time - otherwise your display will be messed up. You can extend that and say that only one task will be using the format buffer at a time, and then it can be a statically array that is shared by all client code.
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2021-11-17 18:19 +0100 |
| Message-ID | <sn3dim$1li1$1@gioia.aioe.org> |
| In reply to | #163439 |
On 11/17/2021 12:04 PM, David Brown wrote: > On 17/11/2021 11:36, pozz wrote: >> Many times I need to construct a string through a call to sprintf and >> pass it to an external function. >> >> char s[32]; >> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); >> lcd_write(s); >> >> The size of s is fixed and calculated for the maximum length of >> yourname, that is 9. >> >> Later in time, I need to change the message into: >> >> sprintf(s, "Hello %s, today is %d/%d/%d", yourname, day, month, year); >> >> Of course, I need to re-calculate the worst-case length, that should be >> now 35. However this is error-prone and I could forget to change the >> size of array. >> >> Is there a better way to manage this situation? I can't use malloc() >> because I'm on an embedded system where I can't use heap. >> >> I'm thinking to use sprintf(NULL, ...), such as: >> >> const char fmt[] = "Hi %s, today is %d/%d/%d"; >> size_t n = sprintf(NULL, fmt, yourname, day, month, year); >> char s[n + 1]; >> sprintf(s, fmt, yourname, day, month, year); >> lcd_write(s); >> > > That would work (with your follow-up correction). You might want to put > a limit on "n" to avoid accidental stack overflow. This arrangement > does mean that you are doing the printf part twice. > > Very often in small systems you know there is a maximum size - if your > screen is 40 characters wide, then 40 characters is enough in your > array. And if you might need up to 40 characters then you might as well > use all of the 40 chars, even though your string might be shorter - you > really don't want to test your code for the name "Al" on date 1/2/2021 > and then find you have a stack overflow on 10/10/2021 with the name > "Rhoshandiatellyneshiaunneveshenk". (Apparently that's a real name - > according to google!) This sounds like good advice. It makes sense to make use of the information given by the maximum string length that can actually be emitted. I'd add the following: 1) use snprintf instead of sprintf; the former is explicitly designed to handle the buffer size limit. 2) use a better format specifier instead of plain "%s" for the string argument, e.g. "%2.12s" Both of the above help preventing buffer overflow, which is something you need to ensure it never happens.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-11-17 20:34 +0100 |
| Message-ID | <sn3lgp$qhj$2@dont-email.me> |
| In reply to | #163448 |
On 17/11/2021 18:19, Manfred wrote: > On 11/17/2021 12:04 PM, David Brown wrote: >> On 17/11/2021 11:36, pozz wrote: >>> Many times I need to construct a string through a call to sprintf and >>> pass it to an external function. >>> >>> char s[32]; >>> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); >>> lcd_write(s); >>> >>> The size of s is fixed and calculated for the maximum length of >>> yourname, that is 9. >>> >>> Later in time, I need to change the message into: >>> >>> sprintf(s, "Hello %s, today is %d/%d/%d", yourname, day, month, >>> year); >>> >>> Of course, I need to re-calculate the worst-case length, that should be >>> now 35. However this is error-prone and I could forget to change the >>> size of array. >>> >>> Is there a better way to manage this situation? I can't use malloc() >>> because I'm on an embedded system where I can't use heap. >>> >>> I'm thinking to use sprintf(NULL, ...), such as: >>> >>> const char fmt[] = "Hi %s, today is %d/%d/%d"; >>> size_t n = sprintf(NULL, fmt, yourname, day, month, year); >>> char s[n + 1]; >>> sprintf(s, fmt, yourname, day, month, year); >>> lcd_write(s); >>> >> >> That would work (with your follow-up correction). You might want to put >> a limit on "n" to avoid accidental stack overflow. This arrangement >> does mean that you are doing the printf part twice. >> >> Very often in small systems you know there is a maximum size - if your >> screen is 40 characters wide, then 40 characters is enough in your >> array. And if you might need up to 40 characters then you might as well >> use all of the 40 chars, even though your string might be shorter - you >> really don't want to test your code for the name "Al" on date 1/2/2021 >> and then find you have a stack overflow on 10/10/2021 with the name >> "Rhoshandiatellyneshiaunneveshenk". (Apparently that's a real name - >> according to google!) > > This sounds like good advice. It makes sense to make use of the > information given by the maximum string length that can actually be > emitted. > > I'd add the following: > 1) use snprintf instead of sprintf; the former is explicitly designed to > handle the buffer size limit. Of course. The OP corrected himself with a follow-up to use snprintf, I believe. > 2) use a better format specifier instead of plain "%s" for the string > argument, e.g. "%2.12s" That is a possibility, but often %s is fine (with the limit you have from snprintf). > > Both of the above help preventing buffer overflow, which is something > you need to ensure it never happens. Indeed.
[toc] | [prev] | [next] | [standalone]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2021-11-18 10:07 +0100 |
| Message-ID | <sn555a$cjo$1@dont-email.me> |
| In reply to | #163439 |
Il 17/11/2021 12:04, David Brown ha scritto: > On 17/11/2021 11:36, pozz wrote: >> Many times I need to construct a string through a call to sprintf and >> pass it to an external function. >> >> char s[32]; >> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); >> lcd_write(s); >> >> The size of s is fixed and calculated for the maximum length of >> yourname, that is 9. >> >> Later in time, I need to change the message into: >> >> sprintf(s, "Hello %s, today is %d/%d/%d", yourname, day, month, year); >> >> Of course, I need to re-calculate the worst-case length, that should be >> now 35. However this is error-prone and I could forget to change the >> size of array. >> >> Is there a better way to manage this situation? I can't use malloc() >> because I'm on an embedded system where I can't use heap. >> >> I'm thinking to use sprintf(NULL, ...), such as: >> >> const char fmt[] = "Hi %s, today is %d/%d/%d"; >> size_t n = sprintf(NULL, fmt, yourname, day, month, year); >> char s[n + 1]; >> sprintf(s, fmt, yourname, day, month, year); >> lcd_write(s); >> > > That would work (with your follow-up correction). You might want to put > a limit on "n" to avoid accidental stack overflow. This arrangement > does mean that you are doing the printf part twice. I know, this is a drawback. > Very often in small systems you know there is a maximum size - if your > screen is 40 characters wide, then 40 characters is enough in your > array. And if you might need up to 40 characters then you might as well > use all of the 40 chars, even though your string might be shorter - you > really don't want to test your code for the name "Al" on date 1/2/2021 > and then find you have a stack overflow on 10/10/2021 with the name > "Rhoshandiatellyneshiaunneveshenk". (Apparently that's a real name - > according to google!) The example was general, because this is a problem I often have: compose a string now to pass to a function. For LCD example, if you use a variable-width font, it's difficult to calc the maximum chars. It depends how many 'i's are in the string. You could consider the worst case of a string composed by all 'i's... > It is also worth noting that only one task should be calling lcd_write > at a time - otherwise your display will be messed up. You can extend > that and say that only one task will be using the format buffer at a > time, and then it can be a statically array that is shared by all client > code.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2021-11-17 05:11 -0800 |
| Message-ID | <8ae929dc-6b89-4a30-bbb0-16ceaeb94c63n@googlegroups.com> |
| In reply to | #163436 |
On Wednesday, November 17, 2021 at 7:36:53 AM UTC-3, pozz wrote: > Many times I need to construct a string through a call to sprintf and > pass it to an external function. > > char s[32]; > sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); > lcd_write(s); > > The size of s is fixed and calculated for the maximum length of > yourname, that is 9. > > Later in time, I need to change the message into: > > sprintf(s, "Hello %s, today is %d/%d/%d", yourname, day, month, year); > > Of course, I need to re-calculate the worst-case length, that should be > now 35. However this is error-prone and I could forget to change the > size of array. > > Is there a better way to manage this situation? I can't use malloc() > because I'm on an embedded system where I can't use heap. > > I'm thinking to use sprintf(NULL, ...), such as: > > const char fmt[] = "Hi %s, today is %d/%d/%d"; > size_t n = sprintf(NULL, fmt, yourname, day, month, year); > char s[n + 1]; > sprintf(s, fmt, yourname, day, month, year); > lcd_write(s); See : asprintf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1248.pdf This function is not implemented in some systems but it can be built with other printf functions. There is also open_memstream that I wish were part of C standard because It cannot be implemented on windows without access to FILE internals. https://linux.die.net/man/3/open_memstream I create my own memory stream to be possible to use on windows and linux.
[toc] | [prev] | [next] | [standalone]
| From | Philipp Klaus Krause <pkk@spth.de> |
|---|---|
| Date | 2021-11-18 15:29 +0100 |
| Message-ID | <sn5o0j$f35$1@solani.org> |
| In reply to | #163441 |
Am 17.11.21 um 14:11 schrieb Thiago Adams: > > See : asprintf > http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1248.pdf asprintf allocates on the heap "as if by malloc", so if he can't use malloc, he can't use asprintf.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-11-17 13:47 +0000 |
| Message-ID | <sn315u$qj7$1@dont-email.me> |
| In reply to | #163436 |
On 17/11/2021 10:36, pozz wrote:
> Many times I need to construct a string through a call to sprintf and
> pass it to an external function.
>
> char s[32];
> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year);
> lcd_write(s);
>
> The size of s is fixed and calculated for the maximum length of
> yourname, that is 9.
>
> Later in time, I need to change the message into:
>
> sprintf(s, "Hello %s, today is %d/%d/%d", yourname, day, month, year);
>
> Of course, I need to re-calculate the worst-case length, that should be
> now 35. However this is error-prone and I could forget to change the
> size of array.
>
> Is there a better way to manage this situation? I can't use malloc()
> because I'm on an embedded system where I can't use heap.
>
> I'm thinking to use sprintf(NULL, ...), such as:
>
> const char fmt[] = "Hi %s, today is %d/%d/%d";
> size_t n = sprintf(NULL, fmt, yourname, day, month, year);
> char s[n + 1];
> sprintf(s, fmt, yourname, day, month, year);
> lcd_write(s);
>
Does lcd_write() remember where it was up to? If so you can break it up:
lcd_write("Hi ");
lcd_write(yourname);
lcd_write(", today is ");
This then only leaves the date, which has a maximum width, eg,
"dd/mm/yyyy". You could also then use a common routine for turning a
date into a string, if it's needed in a few places.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2021-11-17 15:34 +0000 |
| Message-ID | <ei9lJ.146291$I%1.54591@fx36.iad> |
| In reply to | #163436 |
pozz <pozzugno@gmail.com> writes: >Many times I need to construct a string through a call to sprintf and >pass it to an external function. > > char s[32]; > sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); > lcd_write(s); One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer. I generally always reserve enough space for the largest possible legal string, particularly when the buffer is on the stack and is less than a page (4KB) in size.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2021-11-17 07:36 -0800 |
| Message-ID | <24d7df90-3564-407a-999f-a33e774897c5n@googlegroups.com> |
| In reply to | #163445 |
On Wednesday, 17 November 2021 at 15:34:50 UTC, Scott Lurndal wrote: > pozz <pozz...@gmail.com> writes: > >Many times I need to construct a string through a call to sprintf and > >pass it to an external function. > > > > char s[32]; > > sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); > > lcd_write(s); > One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer. > It depends whether wrong results are better or worse than no results.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-11-17 16:56 +0100 |
| Message-ID | <sn38n4$l8i$1@dont-email.me> |
| In reply to | #163446 |
On 17/11/2021 16:36, Malcolm McLean wrote: > On Wednesday, 17 November 2021 at 15:34:50 UTC, Scott Lurndal wrote: >> pozz <pozz...@gmail.com> writes: >>> Many times I need to construct a string through a call to sprintf and >>> pass it to an external function. >>> >>> char s[32]; >>> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); >>> lcd_write(s); >> One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer. >> > It depends whether wrong results are better or worse than no results. > Generally, a truncated string on the output is better than a stack overflow with your embedded system crashing or going wild. But your needs may vary.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2021-11-17 18:21 +0000 |
| Message-ID | <9LblJ.45928$SW5.10995@fx45.iad> |
| In reply to | #163447 |
David Brown <david.brown@hesbynett.no> writes: >On 17/11/2021 16:36, Malcolm McLean wrote: >> On Wednesday, 17 November 2021 at 15:34:50 UTC, Scott Lurndal wrote: >>> pozz <pozz...@gmail.com> writes: >>>> Many times I need to construct a string through a call to sprintf and >>>> pass it to an external function. >>>> >>>> char s[32]; >>>> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); >>>> lcd_write(s); >>> One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer. >>> >> It depends whether wrong results are better or worse than no results. >> > >Generally, a truncated string on the output is better than a stack >overflow with your embedded system crashing or going wild. But your >needs may vary. Indeed. Plus a good programmer checks the return value from snprintf. Always.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-11-17 20:37 +0100 |
| Message-ID | <sn3llm$qhj$3@dont-email.me> |
| In reply to | #163449 |
On 17/11/2021 19:21, Scott Lurndal wrote: > David Brown <david.brown@hesbynett.no> writes: >> On 17/11/2021 16:36, Malcolm McLean wrote: >>> On Wednesday, 17 November 2021 at 15:34:50 UTC, Scott Lurndal wrote: >>>> pozz <pozz...@gmail.com> writes: >>>>> Many times I need to construct a string through a call to sprintf and >>>>> pass it to an external function. >>>>> >>>>> char s[32]; >>>>> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); >>>>> lcd_write(s); >>>> One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer. >>>> >>> It depends whether wrong results are better or worse than no results. >>> >> >> Generally, a truncated string on the output is better than a stack >> overflow with your embedded system crashing or going wild. But your >> needs may vary. > > Indeed. Plus a good programmer checks the return value from snprintf. > Always. > Really? I never do. But I make sure my buffers are the right size for the job - or that it doesn't matter if there is truncation (such as for log outputs). I prefer to be sure that my inputs to the function are correct, than to call the function and check for problems afterwards. (Different people can have different requirements here - but that's the way I do it.)
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2021-11-17 21:35 +0000 |
| Message-ID | <0BelJ.45864$np6.1851@fx46.iad> |
| In reply to | #163453 |
David Brown <david.brown@hesbynett.no> writes:
>On 17/11/2021 19:21, Scott Lurndal wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>> On 17/11/2021 16:36, Malcolm McLean wrote:
>>>> On Wednesday, 17 November 2021 at 15:34:50 UTC, Scott Lurndal wrote:
>>>>> pozz <pozz...@gmail.com> writes:
>>>>>> Many times I need to construct a string through a call to sprintf and
>>>>>> pass it to an external function.
>>>>>>
>>>>>> char s[32];
>>>>>> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year);
>>>>>> lcd_write(s);
>>>>> One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer.
>>>>>
>>>> It depends whether wrong results are better or worse than no results.
>>>>
>>>
>>> Generally, a truncated string on the output is better than a stack
>>> overflow with your embedded system crashing or going wild. But your
>>> needs may vary.
>>
>> Indeed. Plus a good programmer checks the return value from snprintf.
>> Always.
>>
>
>Really? I never do. But I make sure my buffers are the right size for
>the job - or that it doesn't matter if there is truncation (such as for
>log outputs). I prefer to be sure that my inputs to the function are
>correct, than to call the function and check for problems afterwards.
>(Different people can have different requirements here - but that's the
>way I do it.)
>
I often use snprintf in place of strcat. For that purpose, checking the return
value is required.
char buffer[1024];
char *bp = buffer;
size_t remaining = sizeof(buffer);
int diag;
diag = snprintf(bp, remaining, "%s", string_to_append_to_buffer);
if (diag != -1 && diag < remaining) {
bp += diag, remaining -= diag;
} else {
/* Handle overflow/error as necessary */
}
....
The only problem is that the return value for snprintf is 'int', while
the buffer size is size_t; which means on systems with a 64-bit size_t,
the return value isn't large enough to express the correct return value
when the size of the result value exceeds 4GB. Not generally a problem in
actual code, but something to be aware of.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2021-11-19 05:38 -0800 |
| Message-ID | <210d10fe-b9be-4752-986f-ba08ef8ccd76n@googlegroups.com> |
| In reply to | #163456 |
On Wednesday, November 17, 2021 at 6:36:09 PM UTC-3, Scott Lurndal wrote:
> David Brown <david...@hesbynett.no> writes:
> >On 17/11/2021 19:21, Scott Lurndal wrote:
> >> David Brown <david...@hesbynett.no> writes:
> >>> On 17/11/2021 16:36, Malcolm McLean wrote:
> >>>> On Wednesday, 17 November 2021 at 15:34:50 UTC, Scott Lurndal wrote:
> >>>>> pozz <pozz...@gmail.com> writes:
> >>>>>> Many times I need to construct a string through a call to sprintf and
> >>>>>> pass it to an external function.
> >>>>>>
> >>>>>> char s[32];
> >>>>>> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year);
> >>>>>> lcd_write(s);
> >>>>> One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer.
> >>>>>
> >>>> It depends whether wrong results are better or worse than no results.
> >>>>
> >>>
> >>> Generally, a truncated string on the output is better than a stack
> >>> overflow with your embedded system crashing or going wild. But your
> >>> needs may vary.
> >>
> >> Indeed. Plus a good programmer checks the return value from snprintf.
> >> Always.
> >>
> >
> >Really? I never do. But I make sure my buffers are the right size for
> >the job - or that it doesn't matter if there is truncation (such as for
> >log outputs). I prefer to be sure that my inputs to the function are
> >correct, than to call the function and check for problems afterwards.
> >(Different people can have different requirements here - but that's the
> >way I do it.)
> >
> I often use snprintf in place of strcat. For that purpose, checking the return
> value is required.
>
>
> char buffer[1024];
> char *bp = buffer;
> size_t remaining = sizeof(buffer);
> int diag;
>
> diag = snprintf(bp, remaining, "%s", string_to_append_to_buffer);
> if (diag != -1 && diag < remaining) {
> bp += diag, remaining -= diag;
> } else {
> /* Handle overflow/error as necessary */
> }
>
> ....
>
> The only problem is that the return value for snprintf is 'int', while
> the buffer size is size_t; which means on systems with a 64-bit size_t,
> the return value isn't large enough to express the correct return value
> when the size of the result value exceeds 4GB. Not generally a problem in
> actual code, but something to be aware of.
And there is a warning when we compare the result of snprintf (int)
against sizeof that returns size_t.
I put cast and this is very annoying.
char buffer[10];
if (snprintf(buffer, sizeof(buffer), "%s", psz) >= (int)sizeof(buffer)) {
//error
}
Actually sizeof returning size_t requires more casts in other places
of my code.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2021-11-19 07:13 -0800 |
| Message-ID | <7e0740f6-dfff-479b-b6de-1b0afd908318n@googlegroups.com> |
| In reply to | #163495 |
On Friday, 19 November 2021 at 13:38:20 UTC, Thiago Adams wrote:
> On Wednesday, November 17, 2021 at 6:36:09 PM UTC-3, Scott Lurndal wrote:
> > David Brown <david...@hesbynett.no> writes:
> > >On 17/11/2021 19:21, Scott Lurndal wrote:
> > >> David Brown <david...@hesbynett.no> writes:
> > >>> On 17/11/2021 16:36, Malcolm McLean wrote:
> > >>>> On Wednesday, 17 November 2021 at 15:34:50 UTC, Scott Lurndal wrote:
> > >>>>> pozz <pozz...@gmail.com> writes:
> > >>>>>> Many times I need to construct a string through a call to sprintf and
> > >>>>>> pass it to an external function.
> > >>>>>>
> > >>>>>> char s[32];
> > >>>>>> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year);
> > >>>>>> lcd_write(s);
> > >>>>> One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer.
> > >>>>>
> > >>>> It depends whether wrong results are better or worse than no results.
> > >>>>
> > >>>
> > >>> Generally, a truncated string on the output is better than a stack
> > >>> overflow with your embedded system crashing or going wild. But your
> > >>> needs may vary.
> > >>
> > >> Indeed. Plus a good programmer checks the return value from snprintf.
> > >> Always.
> > >>
> > >
> > >Really? I never do. But I make sure my buffers are the right size for
> > >the job - or that it doesn't matter if there is truncation (such as for
> > >log outputs). I prefer to be sure that my inputs to the function are
> > >correct, than to call the function and check for problems afterwards.
> > >(Different people can have different requirements here - but that's the
> > >way I do it.)
> > >
> > I often use snprintf in place of strcat. For that purpose, checking the return
> > value is required.
> >
> >
> > char buffer[1024];
> > char *bp = buffer;
> > size_t remaining = sizeof(buffer);
> > int diag;
> >
> > diag = snprintf(bp, remaining, "%s", string_to_append_to_buffer);
> > if (diag != -1 && diag < remaining) {
> > bp += diag, remaining -= diag;
> > } else {
> > /* Handle overflow/error as necessary */
> > }
> >
> > ....
> >
> > The only problem is that the return value for snprintf is 'int', while
> > the buffer size is size_t; which means on systems with a 64-bit size_t,
> > the return value isn't large enough to express the correct return value
> > when the size of the result value exceeds 4GB. Not generally a problem in
> > actual code, but something to be aware of.
> And there is a warning when we compare the result of snprintf (int)
> against sizeof that returns size_t.
>
> I put cast and this is very annoying.
>
> char buffer[10];
> if (snprintf(buffer, sizeof(buffer), "%s", psz) >= (int)sizeof(buffer)) {
> //error
> }
>
> Actually sizeof returning size_t requires more casts in other places
> of my code.
>
size_t is a nuisance. The justification for it is that sizes of things in memory
may exceed the range of an int. But it turns into a bulldozer. Every count,
every index variable, as well as sizes of things in bytes, become touched by
size_t.
[toc] | [prev] | [next] | [standalone]
| From | William Ahern <william@25thandClement.com> |
|---|---|
| Date | 2021-11-17 20:46 -0800 |
| Message-ID | <pd2h6i-dsm1.ln1@wilbur.25thandClement.com> |
| In reply to | #163453 |
David Brown <david.brown@hesbynett.no> wrote: > On 17/11/2021 19:21, Scott Lurndal wrote: >> David Brown <david.brown@hesbynett.no> writes: >>> On 17/11/2021 16:36, Malcolm McLean wrote: >>>> On Wednesday, 17 November 2021 at 15:34:50 UTC, Scott Lurndal wrote: >>>>> pozz <pozz...@gmail.com> writes: >>>>>> Many times I need to construct a string through a call to sprintf and >>>>>> pass it to an external function. >>>>>> >>>>>> char s[32]; >>>>>> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); >>>>>> lcd_write(s); >>>>> One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer. >>>>> >>>> It depends whether wrong results are better or worse than no results. >>>> >>> >>> Generally, a truncated string on the output is better than a stack >>> overflow with your embedded system crashing or going wild. But your >>> needs may vary. >> >> Indeed. Plus a good programmer checks the return value from snprintf. >> Always. >> > > Really? I never do. But I make sure my buffers are the right size for > the job - or that it doesn't matter if there is truncation (such as for > log outputs). I prefer to be sure that my inputs to the function are > correct, than to call the function and check for problems afterwards. > (Different people can have different requirements here - but that's the > way I do it.) > That is generally the best approach, but doesn't work well with snprintf (or stringification of data types generally), especially in light of the express concern about robustness to drive-by edits of the format string. The way to avoid string buffer errors is to avoid strings and stick to concrete data types or to process data in a rigorously streaming fashion. That's true of C and other languages--strings aren't data structures, they're the antithesis of a data structure. But one nonetheless often finds themselves dealing with strings either on input or output, unfortunately, and facing the cruel economic calculus of worse is better. Which I suppose is why every language spends so much effort chasing a better string type despite the very phrase, string type, being a contradiction in terms.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-11-18 10:50 +0100 |
| Message-ID | <sn57ku$tea$1@dont-email.me> |
| In reply to | #163460 |
On 18/11/2021 05:46, William Ahern wrote: > David Brown <david.brown@hesbynett.no> wrote: >> On 17/11/2021 19:21, Scott Lurndal wrote: >>> David Brown <david.brown@hesbynett.no> writes: >>>> On 17/11/2021 16:36, Malcolm McLean wrote: >>>>> On Wednesday, 17 November 2021 at 15:34:50 UTC, Scott Lurndal wrote: >>>>>> pozz <pozz...@gmail.com> writes: >>>>>>> Many times I need to construct a string through a call to sprintf and >>>>>>> pass it to an external function. >>>>>>> >>>>>>> char s[32]; >>>>>>> sprintf(s, "Hi %s, today is %d/%d/%d", yourname, day, month, year); >>>>>>> lcd_write(s); >>>>>> One might consider using 'snprintf' instead of 'sprintf'; it is a bit safer. >>>>>> >>>>> It depends whether wrong results are better or worse than no results. >>>>> >>>> >>>> Generally, a truncated string on the output is better than a stack >>>> overflow with your embedded system crashing or going wild. But your >>>> needs may vary. >>> >>> Indeed. Plus a good programmer checks the return value from snprintf. >>> Always. >>> >> >> Really? I never do. But I make sure my buffers are the right size for >> the job - or that it doesn't matter if there is truncation (such as for >> log outputs). I prefer to be sure that my inputs to the function are >> correct, than to call the function and check for problems afterwards. >> (Different people can have different requirements here - but that's the >> way I do it.) >> > > That is generally the best approach, but doesn't work well with snprintf (or > stringification of data types generally), especially in light of the express > concern about robustness to drive-by edits of the format string. > It works perfectly well in the type of programming I do. Different kinds of work have different requirements. In small-systems embedded programming (which is what I usually work with, and also what the OP is doing), you know what you are passing to your printf type functions. You know what the output is connected to (a screen, a UART, a log in flash, etc.). But it can be an entirely different matter in other kinds of programming where you might have the format string coming from an external file of translations made by a third party, or the endless variety of complicating factors that can occur on big systems. Scott could be right that a good programmer always checks the return value of snprintf when doing the kind of coding he does - but it is not right for the kind of coding /I/ do. > The way to avoid string buffer errors is to avoid strings and stick to > concrete data types or to process data in a rigorously streaming fashion. The way to avoid string buffer errors is the same as you avoid any other errors - good development practices. That runs the whole gamut from high level concerns to low-level details. It includes making sure you have clear specifications for the code you are writing, making sure the programmer is appropriately qualified, having code review practices, testing regimes, automatic checking tools, making sure the data coming into your code is appropriate, making sure you correctly handle all cases (including worst cases and pathological cases), and so on. It's just like any other coding error.
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web