473,795 Members | 3,393 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

New book - 'C of Peril'

Hello All,

I've been compiling a series of pages about the bad functions and
mistakes that occur in C into a book, subsequently, I now have a moderate
little book of about 32 pages available for download as a PDF file at

http://www.pldaniels.com/c-of-peril

It's currently still being worked on and I'm always seeking out new
examples of C being used poorly or broken standard functions.

Regards.

--
PLDaniels - Software - Xamime
Unix systems Internet Development A.B.N. 19 500 721 806
PGP Public Key at http://www.pldaniels.com/gpg-keys.pld
Nov 14 '05 #1
56 2605
In article <pa************ *************** *@pldaniels.com >,
Paul L Daniels <pl*******@plda niels.com> wrote:
Hello All,

I've been compiling a series of pages about the bad functions and
mistakes that occur in C into a book, subsequently, I now have a moderate
little book of about 32 pages available for download as a PDF file at

http://www.pldaniels.com/c-of-peril

It's currently still being worked on and I'm always seeking out new
examples of C being used poorly or broken standard functions.


I looked quickly through your writeup. It's pretty good.
Here are my remarks on a couple of items that sort of jumped at me.

1.
On the section on free() you wrote:

Certainly it is agreeable that if you are attempting to free a
null pointer, then you're most certainly in a situation where
somewhere prior in your code there is something amiss.

Certainly it is agreeable? Not!

I free() NULL pointers frequently and intentionally. Here is a sample:

void somefunction(vo id)
{
char *x, *y, *z;

x = malloc(100);
y = malloc(100);
z = malloc(100);

if (x==NULL || y==NULL || z==NULL)
goto cleanup;

/* do some real work here */

cleanup:
free(x);
free(y);
free(z);
}

Suppose that the first call to malloc() succeeds but the 2nd
and 3rd calls fail. Then free() is called with non-NULL x
but with NULL values for y and z. Nothing wrong with that.
And certainly it's not true that "there is something amiss".
2.
On the section on macros, you suggest:

#define foo(x) { bar(x); baz(x); }

This is not really good. For example, the following
snippet will not compile:

if (sometest)
foo(x);
else
fubar(x);

You want to change the macro to the canonical form:

#define foo(x) do { bar(x); baz(x); } while(0)

--
Rouben Rostamian
Nov 14 '05 #2
Up spake Rouben Rostamian:
#define foo(x) do { bar(x); baz(x); } while(0)


This will still cause problems if the parameter has side effect(s).
Consider:

#define foo(x) do { bar(x); baz(x); } while(0)
foo (printf ("oops!"));

If you know the type of x in advance[0], you can create a local
variable. Consider:

#define foo(x) do { int y = (x); bar (y); baz (y); } while (0)

However, this in turn causes problems with variable capture. Consider:

#include <stdio.h>
#define foo(x) do { int y = (x); bar (y); bar (y); } while (0)

void bar (int y) { printf ("%d ", y); }

int main (void) {
int x, y;

x = y = 4;
foo (x + y);
printf ("%d\n", y);

return 0;
}

Intuitively, one would expect this to print "8 8 4". On my system, it
prints "1091899344 1091899344 4", because the symbol `y' in `foo (x +
y)' refers to the inner declaration's variable, which is noninitialized.

The only workaround I have found to prevent variable capture is to give
the macro variable an obscure name (e.g. `mypackage_myma cro_myvariable' )
and hope nobody else uses it.

[0] OT: The GNU typeof extension provides genericity here.
--
-trent
Support bacteria! It's the only culture some people have.
Nov 14 '05 #3
Rouben,

First up, thanks for the responses, always welcome so you can bet that
there will be some changes made :-)
I free() NULL pointers frequently and intentionally. Here is a sample:
Do you run into portability issues relying on this behavior?
x = malloc(100);
y = malloc(100);
z = malloc(100);
Now, perhaps this is going to open up a can of worms, but would it not be
prudent to check the state of x/y/z _before_ proceeding to the next
malloc? I realise that it makes for longer, possibly even messier code,
however is it not more "right" to check after each malloc?
if (x==NULL || y==NULL || z==NULL)
goto cleanup
I can see someone jumping on this one (goto debates are always amusing).

You want to change the macro to the canonical form:

#define foo(x) do { bar(x); baz(x); } while(0)


Anyone know if there's a way to do this without relying on do/while/if/for
(etc)?

Or are we bound to these one-shot do/while loops in order to handle the
trailing ';' ?
Regards.
--
PLDaniels - Software - Xamime
Unix systems Internet Development A.B.N. 19 500 721 806
PGP Public Key at http://www.pldaniels.com/gpg-keys.pld
Nov 14 '05 #4
I should point out that the 'macros' section is one of the less mature
sections in the book, hence it's good that you guys (girls?) are chewing
on it.
The only workaround I have found to prevent variable capture is to give
the macro variable an obscure name (e.g. `mypackage_myma cro_myvariable' )
and hope nobody else uses it.


It would seem to me that for every (sane) macro solution that is derived,
there lies a newly created problem situation where it won't work. This in
itself is precisely why this book is being written, even if you cannot
derive complete solutions, increasing the awareness of the problems is a
desired goal.

Trent, I'd like to consider inserting the sequence of macro
attempts/failures that you have just presented (perhaps modified a litte)
as an 'example' of how macros can go wrong.

Kindly,
Paul.

--
PLDaniels - Software - Xamime
Unix systems Internet Development A.B.N. 19 500 721 806
PGP Public Key at http://www.pldaniels.com/gpg-keys.pld
Nov 14 '05 #5

On Sun, 5 Dec 2004, Paul L Daniels wrote:

I've been compiling a series of pages about the bad functions and
mistakes that occur in C into a book, subsequently, I now have a moderate


Incidentally, that introductory paragraph shows about the quality of
English writing we can expect from the whole book --- not so hot. I
have relatively little complaint with the actual technical content of
the document, but the presentation is awful. At the very /least/ run
a spell-checker on the text, and I'd recommend getting a good reader
to look it over for clarity before unleashing it on the unsuspecting
populace, as it were. </rant>

<rant mode=continue> Oh, and for Pete's sake don't use hard tabs on
Usenet! </ok done now really>
2.1: 'strcpy' is definitely not the first function I'd go to in the
"peril" department. After all, it's perfectly safe when used correctly,
and incredibly hard to mess up. Even in your example, you have to resort
to a function in which you declare a length ('10') and then proceed to
forget you ever declared it.
You should find out how to keep figures and code listings on one page
of the generated PDF, and use that feature liberally. It's hard to read
code that jumps across pages unnecessarily.
The second source listing has an extraneous ':' character in it.

2.2: "wil not" is spelled "will not" on my Red Hat system. I don't
know what system you have. (Google does provide circumstantial evidence
for the "wil not" spelling, 104 to 88.)
The correct fix for this 'printf' error is to use the "%*s" format
specifier instead of the "%s" specifier, and pass 'FOO_STR_LEN' to
'printf' yourself.
Returning 'NULL' from 'CP_strncpy' under any circumstances strikes
me as highly dangerous. Do you know why 'strcpy' and family always
return the destination pointer?
What will the following code do, and why? Try to answer first without
looking at the source code of 'CP_strncpy'.
char arr[10];
CP_strncpy(arr, "hello", strlen("hello") );

2.3: C++ programmers will not like that you use a struct with the
same name as a function.

2.4: Why 'CP_strncpy' but 'zstrncat'? Is there a method to your naming
convention?
Several of your single-line comments spill over and become syntax
errors; this is exactly why Real Programmers[tm] do not use C++-style
comments.

2.5: Are you going to explain /how/ to use 'snprintf' to emulate
'strncpy' (or rather, what you think 'strncpy' ought to be doing)?
I bet you'll have at least one reader who wonders why
snprintf(dst, n, src);
does not always work as expected.

3.1: A more realistic example (i.e., one that would do something
reasonable if it worked) would be helpful here. Your current example
merely loops forever --- who cares what it's doing with memory? Fixing
the "bug" won't make the program work!
Your "safe" usage contains at least one instance of undefined behavior,
not counting the obvious one.
You don't discuss a real-life programming error which I have recently
encountered in my own code --- /twice/!

int k, *pids = NULL;
int pids_len=0, pids_cap=0;
while ((k=getpid()) != NULL) {
/* Do we need to resize the |pids| array? */
if (pids_len >= pids_cap) {
void *v;
pids_cap = pids_cap*2 + 15;
v = realloc(pids, pids_cap);
if (v == NULL) do_error("Out of memory");
pids = v;
}
/* Add the new pid */
pids[pids_len++] = k;
}
/* Process array |pids|, and free it when we're done */
free(pids);
return;

3.2: "Redundant code makes for slower and larger programs." Are
you claiming that the statement 'free(p);' is more redundant than
the statement 'if (p != NULL) free(p);'? I don't think you'll find
many takers.
Listing 3.3 is labeled "Example of segmentation faulting using free,"
but it does not exhibit a segfault --- it's perfectly valid. Remove
the '= NULL' initializer and you've got a case.
Your "graceful exit" uses the non-portable expression 'exit(1)'.

3.4: 'sizeof' is not a function.
You are writing about C99 (since you use C++-style comments in earlier
listings). Therefore you should know that 'sizeof' is no longer strictly
a compile-time construct, when you're dealing with VLA expressions.
Your "As a rule" goes utterly against the comp.lang.c majority opinion.
Read the archives for enlightenment on both sides of this debate.

4.1: Do you know about
if ((p = strchr(buffer, '\n'))) *p = '\0';

4.3: Do you know about the * modifier?

4.4: 'syslog' is not a standard C function. You might want to explain
where it's used; I for one have never heard of it, and have no idea what
'syslog(1, ...)' is supposed to do.
The assumption that large compiles must necessarily generate lots of
spurious warnings is a dangerous one. Consider fixing warnings as they
appear.

5.2: Your example code is right. This would normally be a good thing,
but in this case you're supposed to be illustrating /wrong/ code.

5.3: The original example code for 5.2 will do nicely; consider
both the "bottom-up" case 'min(1&2, 1&3)' and the "top-down"
case '1 + min(1,2)'. Ditto for 5.4.

5.5: Note that the given output is only hypothetical; the program
exhibits undefined behavior.

5.6: Others have already pointed out the error and the textbook
solution. You might also consider addressing the pitfall of

#define foo(x) do { \
bar(x); \
baz(x); \
} while (0) \
#define bar(x) do { \
wubble(x); \
} while (0) \

Yes, it's easy to catch and easy to fix, but then so are many of the
problems you address.

6: "programmin g ... is not the place to express creativity ..."
Obviously you have never programmed!

6.1: However, note that a source file full of /too/ many characters
can be even worse! I'm sure you can find examples in the newsgroup
archives of instances in which our regulars have dissected newbie
programs redolent with excess parentheses and levels of nesting, only
to discover that the underlying algorithm can be expressed in five
lines of concise and idiomatic code. (By which I do /not/ mean Ben
Pfaff's signature file! When /I/ use the word "idiomatic, " it is a
compliment!)

I hope these comments help you improve the book's technical content.
And remember what I said about the proofreader.

-Arthur
Nov 14 '05 #6

On Sun, 5 Dec 2004, Paul L Daniels wrote:

Rouben,
I free() NULL pointers frequently and intentionally. Here is a sample:


Do you run into portability issues relying on this behavior?


Why should he? The only implementations that have problems with
freeing null pointers are pre-C89 versions, which are generally not
supported anymore except by the most venerable of programs (Nethack,
for example, still supports K&R C, AFAIK). And in your book, you're
assuming C99 already!
x = malloc(100);
y = malloc(100);
z = malloc(100);


Now, perhaps this is going to open up a can of worms, but would it not be
prudent to check the state of x/y/z _before_ proceeding to the next
malloc? I realise that it makes for longer, possibly even messier code,
however is it not more "right" to check after each malloc?


Didn't you complain in section 3.2 about redundant code?

#define foo(x) do { bar(x); baz(x); } while(0)


Anyone know if there's a way to do this without relying on do/while/if/for
(etc)?


Nope. But why does it matter? 'do' is just as much a part of the
language as the left parenthesis, and it always has been.

-Arthur
Nov 14 '05 #7
Up spake Paul L Daniels:
Trent, I'd like to consider inserting the sequence of macro
attempts/failures that you have just presented (perhaps modified a litte)
as an 'example' of how macros can go wrong.
I hereby release the macros I wrote upthread to the Public Domain. I
consider everything I post on Usenet to be PD, but it's commendable of
you to ask.
It would seem to me that for every (sane) macro solution that is derived,
there lies a newly created problem situation where it won't work. This in
itself is precisely why this book is being written, even if you cannot
derive complete solutions, increasing the awareness of the problems is a
desired goal.


The Paul Graham has a lot to say about macros and the accompanying
problems. Not in C, but the issues are similar.

http://www.bookshelf.jp/texi/onlisp/..._13.html#SEC68
http://www.bookshelf.jp/texi/onlisp/..._14.html#SEC78

--
-trent
Ah! my brave Ned, do you know how many square inches you carry on the
surface of your body? -- Not in fact Grytpype-Thynne
Nov 14 '05 #8
Arthur,

Ahh, the warm welcome-back of newsgroups.
Incidentally, that introductory paragraph shows about the quality of
English writing we can expect from the whole book --- not so hot.
Never claimed it to yet be an exercise in English literature. The book is
incomplete and will go through an editing phase by 3rd parties.
[...many useful hints and questions...]
I hope these comments help you improve the book's technical content.
And remember what I said about the proofreader.


The book will be ammended, updated as usual, in a never ending cycle (it
would seem). As always, I do appreciate the input. If there's one thing
to be aware of, it is that you can never know everything (your comments
have proven that much - though I didn't need it proven ;-).

Regards.

--
PLDaniels - Software - Xamime
Unix systems Internet Development A.B.N. 19 500 721 806
PGP Public Key at http://www.pldaniels.com/gpg-keys.pld
Nov 14 '05 #9
Up spake Paul L Daniels:
You want to change the macro to the canonical form:

#define foo(x) do { bar(x); baz(x); } while(0)
Anyone know if there's a way to do this without relying on do/while/if/for
(etc)?


The other technique I sometimes see is !!GNU EXTENSION!! expressions
within statements. Consider this !!NON STANDARD!! assertion wrapper:

#ifdef PROHIBIT_STATEM ENT_EXPRS
/* WARNING! assert_lambda() macros will not assert,
* because statement expressions are prohibited.
*/
# define defun_assert_la mbda(TYPE,TEST, FUNC) FUNC
#else
# define defun_assert_la mbda(TYPE,TEST, FUNC) \
({ \
TYPE aug_assert_lamb da_x; \
assert \
(TEST != (aug_assert_lam bda_x = FUNC)); \
aug_assert_lamb da_x; \
})
#endif
#define assert_malloc(A ) \
defun_assert_la mbda (void*, NULL, malloc(A))

....I don't recommend it, for obvious reasons.
Or are we bound to these one-shot do/while loops in order to handle the
trailing ';' ?


Yes, but they only *look* ugly; there's nothing else wrong with them.

--
-trent
On two occasions I have been asked [by members of Parliament], `Pray,
Mr. Babbage, if you put into the machine wrong figures, will the right
answers come out?' I am not able rightly to apprehend the kind of
confusion of ideas that could provoke such a question.
-- Charles Babbage
Nov 14 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
2429
by: anonymous | last post by:
Hi CLCers, I want to know your opinion about the book: Expert C programming-Deep C secrets by Peter Van Der Linden. Thanks in advance. Sha
12
2122
by: Guido Mureddu | last post by:
Hello, I'm a student in electronic engineering. I do know you've seen and answered this sort of topic/request countless times, but I haven't found past threads as helpful as I had hoped, and even though I have read them all and many reviews, I prefer to ask directly to people who know the subject better than anyone else. First of all, I'm not new to programming, and I have already had an introductory course on C. I have an...
16
8511
by: Robert Zurer | last post by:
Can anyone suggest the best book or part of a book on this subject. I'm looking for an in-depth treatment with examples in C# TIA Robert Zurer robert@zurer.com
8
2197
by: Dgates | last post by:
Has anyone typed up an index for the O'Reilly book "C# and VB.NET Conversion?" I'm just learning C#, and often using this little book to see which VB.NET terms translate directly to some term in C#. However, it's a real hassle that the book has no index, just a table of contents. For example, as early as page 8, the book teaches that C#'s "using" statement is the equivalent of VB.NET's "imports" statement. However, that concept...
11
1934
by: www.douglassdavis.com | last post by:
I'm looking for advice here, and I would really appreciate it if you could help. Is there a VB 2005 book that you like and would recommend (and why)? Would you consider it good for beginners to programming, intermediate, or advanced level?
263
9405
by: Malcolm McLean | last post by:
The webpages for my new book are now up and running. The book, Basic Algorithms, describes many of the fundamental algorithms used in practical programming, with a bias towards graphics. It includes mathematical routines from the basics up, including floating point arithmetic, compression techniques, including the GIF and JPEG file formats, hashing, red black trees, 3D and 3D graphics, colour spaces, machine learning with neural...
6
1988
by: Hello | last post by:
Hello every body Please can any body tells me a good book that can teach me "visual basic 2005" (as beginner). Thank you all =========================================
1
3591
by: jrw133 | last post by:
i got this program the other day and ive just started it and i am getting some errors that i cant figure out. requirements: 1)create a clas called Book. a Book has three data members: m_title, m_id and m_flag to tell whether the book is in or checked out. 2)Write a constructor for Book. write a constructor that takes 3 parameters: Book(char * title, int id, bool flag) and initializes the 3 data members accordingly. in addition print out a...
76
4096
by: lorlarz | last post by:
Crockford's JavaScript, The Good Parts (a book review). This shall perhaps be the world's shortest book review (for one of the world's shortests books). I like Douglas Crockford (because I am a crabby old man too; plus he _is_ smart and good).. But, how can he write a book on the good parts of JavaScript and not mention functions that address CSS & DOM? Weird. It's like
0
9672
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9519
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10437
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10214
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10164
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7538
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5563
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4113
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2920
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.