Bug 25214 - ctype.h performance (and potentially behavior) depends on include order
Summary: ctype.h performance (and potentially behavior) depends on include order
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.27
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2019-11-22 01:21 UTC by Travis Downs
Modified: 2020-02-19 15:19 UTC (History)
2 users (show)

See Also:
Last reconfirmed:
fweimer: security-


Note You need to log in before you can comment on or make changes to this bug.
Description Travis Downs 2019-11-22 01:21:45 UTC
At least one some versions of libc, whether you include <stdlib.> before or after <ctype.h> changes the way the toupper and tolower functions are defined.

See for example here:


If you include the <ctype.h> header first, the bodies of extern inline functions are exposed in the header, and are inlined (note the loop contains no toupper call). If you swap the order, and include <stdlib.h> first, then __NO_CTYPE gets defined somewhere in the header chain, and when <ctype.h> is included the inline bodies are not available, and so inlining doesn't happen.

See the block guarded by __NO_CTYPE in ctype.h at:


At least this causes a large performance variation (I measure the non-inlined version as 3 to 4 times slower), but if you pick through that conditionally defined block I bet you can find functional differences too.

I would expect __NO_CTYPE to defined consistently regardless of header include order.
Comment 1 joseph@codesourcery.com 2019-11-22 01:43:40 UTC
Are you compiling as C++?  Some libstdc++ headers define __NO_CTYPE 
(because C++ prohibits headers from defining standard functions as 
macros), but I don't see anything in the glibc headers defining that 
Comment 2 Travis Downs 2019-11-22 01:46:58 UTC
Yes, I'm compiling as C++, and I should have made that clear from the start.

In C, the flow is totally different and toupper/tolower are macros, not functions (as you pointed out).

Although I'm compiling as C++, the only headers I'm including are <stdlib.h> and <ctype.h>. I'm not sure exactly where __NO_CTYPE is getting defined in this case, but in another case I looked at (this time including C++ headers like <algorithm>, the __NO_CTYPE definition came from <bits/os_defines.h>).
Comment 3 Travis Downs 2019-11-22 01:49:39 UTC
Here's an example that shows that <stdlib.h> defines __NO_CTYPE when compiled in C++:


In C it is not defined.