Topic: safer printf
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 28 May 1994 15:39:39 GMT Raw View
Well, I warned you :-)
----------------------------------------------------------------
ISO: WG21/N0xxx
ANSI: 94-xxxx
Author: John Max Skaller
Date: May 1994
Reply to: maxtal@suphys.physics.su.oz.au
"TYPE SAFE PRINTF"
------------------
Although we have iostreams, may programmers continue
to use the C streams. They are after all, part of the C++
Standard Library.
I have found its very common using the formatted IO functions
to get the types wrong:
long ch;
printf("%d", ch); // wrong
in some cases, its not even so easy to get it right portably:
size_t n;
printf("%d", n); // implementation dependency!
Well, C programmers have "lint", but we've got real compilers!
Proposal
--------
In calls to the Standard Library functions
printf(),
sprintf(),
fprintf(),
vsprintf(),
scanf(),
sscanf(),
fscanf() and
vscanf()
and matching wide character versions of these functions,
if the format control argument is given as a C style null
terminated string literal, then
the arguments will be type checked and a diagnostic issued
if insufficient arguments are given, or arguments of a type which
would lead to undefined behaviour are given.
No diagnostic is required otherwise. Whether and how
vendor extensions to the format codes are checked is
implementation defined.
Example
-------
const char * fmt = "%d";
long l;
printf(fmt, l); // undiganosed error
printf("%d",l); // ill-formed, diagnostic required
printf("%d",
Compatibility:
--------------
NO change to the language is intended. This proposal
simply requires a diagnostic for easily detectable
errors, where previously no diagnostic was required.
Question: Why should an error be diagnosed if the function is not
actually called?
Answer: Thats normal behaviour in other cases where types are checked.
Question: Why should implementors be required to go to the extra
trouble, especially for a C feature?
Answer: There is some work involved for implementors, but
not much compared to the hours lost by programmers writing
bad function calls. This error is one of the _most_ common
made by myself and others on my programming team.
Answer 2: Often, we dont even know which format codes to use.
Programmers typically rely on compilers, and not reference
books or Standards to answer questions about what is OK and what isnt.
Question: Why not just make it a quality of implementation issue?
Answer: Because very few compilers today actually perform this
check, and they have had plenty of time to implement it.
Experience shows many vendors will not provide functionality
not required by their target environment or the Standard.
Requiring a diagnostic allows one to examine code that is
accepted by a conforming compiler and tell immediately
that most calls to this class of function cannot be causing
a problem.
Adding such safety guarrantees to a language enhances
the ability to diagnose faults.
Question: Why only string literals?
Answer: Because it makes sense for the compiler, and user,
to check what is literally visible, and the case
of a general expression is not statically checkable.
In many applications, especially where printf()
is suitable (such as for debugging), the format controls
wil be literals.
Question: But we dont want to promote use of these functions!
We have iostreams. Why should we do this?
Answer:
a) A lot of C programmers upgrading to C++
will write using familiar functions and idioms.
b) If we havent the courage to deprecate these functions,
we should make them as safe as possible.
c) C++ has a philosophy of supporting multiple paradigms.
d) The C functions are Standardised, well understood,
and used frequently. Many people like them, and some
even prefer them to iostreams (including me).
I believe we have no right to prevent programmers
making this decision, and we should support this
usage by diagnosing errors when possible.
e) There is a large body of existing C code that
may be ported to C++ compilers. Often implementation
assumptions such as that a size_t is the same size
as an int change, and the printf family may silently
fail in these cases unless a diagnostic is mandated.
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA
Author: jason@cygnus.com (Jason Merrill)
Date: Sun, 29 May 1994 00:54:48 GMT Raw View
Note that gcc already implements a warning for errors like this. g++ does
not as of 2.5.8, but will in 2.6.0.
Jason