- xkcd, "The History of Unicode" - 1 Update
- Why it is important to check what the malloc function returned - 2 Updates
Lynn McGuire <lynnmcguire5@gmail.com>: Feb 11 04:27PM -0600 xkcd, "The History of Unicode" https://xkcd.com/1953/ Lynn |
David Brown <david.brown@hesbynett.no>: Feb 11 04:16PM +0100 On 09/02/18 18:48, James Kuyper wrote: > that could only come up because that construct was permitted: the > possibility of forgetting to #include the appropriate header, and > getting no warning about the declaration being missing. I realise that. And I can understand the reasoning for worrying about accidentally using undeclared functions in 1987. I can't understand worrying about it now, because tools will detect it. Even if you have to use an older or more limited compiler (and sometimes you do), you can use additional tools for checking. Many editors will do it. > C90. Modern implementation that have a C90 mode often warn about this, > but it's still often optional, and was not as common before C99 came out > as it is now. C99 came out /long/ ago. Yes, there are still C90-only compilers in use. Yes, there are compilers with limited warnings in use. There can be a number of reasons why you need to compile code with tools that have little or no ability to spot such errors. I have occasion to use these sorts of tools myself when making changes to old projects. But there is a big difference between what you need to use while /building/ code, and what you can use while /developing/ code. Your build environment might consist of an ancient C90 compiler, because that is the one that is tested and qualified for the project. Or it might consist of a new C90-only compiler, because that is the only one that exists for the weird processor you are using. Or you might have no idea about the build environment because there are thousands of people using the code with all sorts of tools and flags. However, as the developer, /you/ control the development environment. /You/ choose to use a smart editor/IDE that checks as you go along, or run pc-lint, or clang-analyzer, or whatever. /You/ choose to have standards that you follow, common development patterns, standard headers that you always use, code reviews with colleagues, etc. You might, for many reasons, not have a build process that makes it easy to catch mistakes like missing function declarations. But there are so many ways to catch it as part of the development process that it is not something to code around - not for development /today/ at least. Twenty years ago, maybe even ten years ago, you could argue that omitting the cast on malloc lead was a code safety point - not now. > vitriol against those who object to it would be more understandable. But > I know of none, (and I've heard the faulty arguments of those who think > it makes their code safer a great many times). I am only arguing here that the code safety reason for not casting malloc is a moot point - you can have other good reasons. Personally, I use malloc so rarely that I can't really say whether I would use a cast or not. For example, I believe the cast /does/ add to code safety if the pointer definition was far from the malloc call - but I would also say it is usually much better to put the pointer definition at the malloc call (to initialise the pointer), negating that point. The overriding issue for me is to decide what makes code clearer, and I don't think a categorical answer can be made. (The exception is if the code needs to be compiled as C++, in which case there is only one possible choice - use the cast.) > the construct, and not getting any warning about the fact. > It's also about not writing code that serves no useful purpose, and that > applies even to more modern C compilers. I agree that you should not write code that serves no useful purpose. I don't agree that the cast necessarily is without purpose. >> I don't see casting malloc()s as a mistake. > That's too bad - you really should understand the reasons why it was (in > C90). It's an important example of how not to design a computer language. I am not sure I follow you. I understand why C allows void* to be converted without a cast. I understand why C++ does not allow that, and why such implicit conversions are a bad idea (along with many other "implicit" things in C, such as "implicit int".) And I understand why it was reasonable to think that omitting a cast on malloc results was a safety point in C coding long ago. I simply don't agree that it is a relevant safety point /now/, even for C90 programming. > it). It's getting the right size - and that's something that can be > arranged perfectly by using malloc(count * sizeof *p), without needing > to know or care about what type *p is. I appreciate that idiom, and it can be useful at times - but it is certainly not the only way to allocate memory. And if the omission of the cast makes such code clearer, less repetitive and has lower risk of error, then I entirely agree - omit the cast in such cases. But if you have a different arrangement for your malloc and the cast makes the code clearer or safer, then use it. And if you don't know or care what type *p is, why are you using it in the first place? |
James Kuyper <jameskuyper@verizon.net>: Feb 11 01:33PM -0500 On 02/11/2018 10:16 AM, David Brown wrote: > On 09/02/18 18:48, James Kuyper wrote: >> On 02/09/2018 12:10 PM, David Brown wrote: ... > I realise that. And I can understand the reasoning for worrying about > accidentally using undeclared functions in 1987. I can't understand > worrying about it now, because tools will detect it. [Note to others reading this message: since this discussion is occurring on comp.lang.c++, it might seem odd, but this part of the discussion has actually been about the behavior of malloc() under C, not about std::malloc() under C++. Thread drift - sorry. Under C++, a cast is unambiguously required, and that is not a point under contention.] It isn't a significant worry now. But because it takes EXTRA effort to insert the cast, with no associated benefit, the insignificant worry about the possibility of the code getting compiled as C90 should be more than sufficient to tip the scale. > use malloc so rarely that I can't really say whether I would use a cast > or not. For example, I believe the cast /does/ add to code safety if > the pointer definition was far from the malloc call - but I would also It doesn't. No matter how far away the declaration is from the point of use, you can be quite certain that if the following line compiles without a diagnostic, then p = malloc(count * sizeof *p); will either result in p containing a null pointer, or pointing at a block of memory sufficiently large to to contain 'count' objects of whatever type p points at. Inserting the cast only creates an error if the type of *p is changed, an error that would not have been an error if the cast had not been inserted. It's a trivially identified and corrected error, but that correction is unnecessary extra work created by insertion of an unnecessary cast. ... > converted without a cast. I understand why C++ does not allow that, and > why such implicit conversions are a bad idea (along with many other > "implicit" things in C, such as "implicit int".) ... That isn't an "other ... thing". This is one aspect of "implicit int": undeclared functions were implicitly declared as returning "int", and that's precisely the feature I was referring to when I said this was "an important example of how not to design a computer language". It's important because the problem is subtle: well-chosen default behavior generally makes things easier to use - but this particular default was not well-chosen, because it made things more dangerous; understanding why is something a language designer should learn. > it was reasonable to think that omitting a cast on malloc results was a > safety point in C coding long ago. I simply don't agree that it is a > relevant safety point /now/, even for C90 programming. People (not many) are still using compilers that either don't warn about this, or need to have options turned on to warn about it, and many of those users are unaware of the desirability of doing so. If there's any danger that my code will compiled by such people (possibly after being cut-and-pasted out of it's normal context), writing it without a cast both saves me a small amount of typing, and gives them a benefit. If inserting the cast had any actual benefit (as it does, for instance, in C++, where it's mandatory), it would be a different matter. ... > error, then I entirely agree - omit the cast in such cases. But if you > have a different arrangement for your malloc and the cast makes the code > clearer or safer, then use it. I've seen claims that such situations can occur, and examples that were intended to support those claims - none of which actually did so. > And if you don't know or care what type *p is, why are you using it in > the first place? If you're using code involving pointers to 20+ different types (which, in my experience, isn't particular uncommon), it's convenient to be justifiably certain that p = malloc(count * sizeof *p); does the correct thing without having to remember or look up which of those 20+ different types p points at, something that you would be required to do if it were written with a cast. It's trivial to confirm that the cast is correct if the malloc() call is the initializer for p, but in precisely that context, inserting the cast is a particularly jarring redundancy, not a useful safety measure. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment