|
| | #26 |
|
Posts: n/a Hébergeur: | jacob navia wrote: > > Using the gcc compiler without any optimizations produces perfectly > valid code that works as intended. Using the 64 bit > gcc compiler (versions 3.3 to 4.3) produces the intended > result even with maximum optimization. By chance, if the construct invokes UB. > Using the PowerPC IBM compiler works with optimizations > and without them. By chance, if the construct invokes UB. > This code was working with gcc-3.3.6 and stopped working only with > gcc 4.1.2 with optimization levels higher than 2 and only in linux 32 > bits. MSVC windows 32 compiler compiles that code correctly. That's what happens if the construct invokes UB. Any tool change can break the fragile code. > How are the maintainers supposed to know that? Should they care? > Because after 2 weeks of work and work finally we examined the > gcc generated assembler and discovered that gcc generates code > to read from an UNINITIALIZED memory location. Post the source and the generated assembler. > When I write > > char tab[5]; > char *p = tab; > > p += 10; > char c = *p; > > this is UB too but will be UB in debug mode AND in release mode. > The value in C will be undefined, but it will be CONSISTENT. No, it won't. It's undefined. p might point at a location that was written by the last programme to run. Even if the value did appear consistent, as soon as the surrounding code changes, it is likely to change. > You are just saying the obvious: > > C++ is not maintainable without huge efforts. Poorly written code in any language that relies on undefined behaviour is not maintainable. C and C++ just happen to give you more rope to hang your self. At least C++ has attempted to shorten the rope by adding specific and easily searchable casts. > It is very easy to laugh at the maintenance programmers here. They > are just stupid of course, since if they weren't, they wouldn't be > in maintenance of course! Boy you have a flea up your arse this weekend. Most people here are probably maintenance programmers. Anyone not working on a green field project can be considered a maintenance programmer. -- Ian Collins |
|
| | #27 |
|
Posts: n/a Hébergeur: | On 11 Jul., 00:54, Joshua Maurice <joshuamaur...@gmail.com> wrote: [snipped discussion about run-time error when OP accessed uninitialized memory. OP complained that C++ compiler (gcc) could not detect this even though its warning level was set to highest] > You seem to be taking the opinion that compilers should catch all > undefined behavior. C++ is not Java. C++'s stated primary design goals > include > - runtime performance comparable with assembly > - don't pay for what you don't use > - portable > - easy to write code / programmer productivity (with less relative > emphasis on this one IMHO) > > With these design goals in mind, it is not reasonable to expect a > compiler to catch all possible undefined behavior or errors. To do > that would necessarily restrict the language so that it's less > comparable to assembly in speed and/or you start paying for things you > don't use. > > In the C and C++ community, the assumption is that the programmer > knows what he's doing, and with that assumption, you can (relatively) > easily write really fast and portable code. Just to add my two cents: 1. C++ lets you do everything, so chances are not bad that you can go beyond your depth. In contrast to this, JAVA restricts your abilities (no messing around with pointers), which makes your code inherently safer. I think both are inferior to programming languages like Ada95. Ada has a real type system (something that neither C++ nor JAVA has) and will perform zounds of checks (it is the only language I know that handles integer overflows). Since these checks give you a lot of performance penalties, you have to provide additional information about which checks can be omitted. This is maybe the major difference between C++ and Ada95: Out of the box C++ provides few checks in favor of speed, whereas Ada95 has all checks turned on. So C++ you have to OPT-IN for run-time checks, Ada95 has the converse OPT-OUT philosophy. Needless to say, nobody uses Ada95 except the Bundeswehr in Germany (AFAIK). 2. Maybe even such fancy languages like Ada cannot reliably detect memory aliasing issues because it may be the case that this task is Turing hard. I haven't had time to think about it in detail, but I think that you could reduce the HALTING problem to the problem of accessing uninitialized memory through aliasing. This would explain why the compiler industry didn't come up with a "decent" compiler: It just may be that detecting _ALL_ such errors is simply impossible (which doesn't mean that there may be a good heuristic algorithm for detecting most of the obvious bugs). I further assume that most cases where you get UB are also due to the impossibiliy to check for such cases algorithmically. @jacob: Don't complain about the gcc team, the problem is definitely in your code. Since you mess around with raw pointers, you're asking for trouble (or rather the guy that wrote the code). Cheer up, you have one of the worst jobs of the world of programming: Inheriting code for your predecessor (some people say that this is what object orientation is all about ;-), and having to find the bugs in this code. Practically noone will give you credit for this, you're more or less just a scape-goat. Personally, I have made little else than re-write code that has been written by physicists (which should be prohibited to writing code by law :-) for the last ten years. I can imagine that bugfixing such code must be a lot more frustrating, so be assured that you have our deepest sympathy. Regards, Stuart |
|
| | #28 |
|
Posts: n/a Hébergeur: | On Jul 14, 10:40 am, Stuart Redmann <DerTop...@web.de> wrote: > On 11 Jul., 00:54, Joshua Maurice <joshuamaur...@gmail.com> wrote: > [snipped discussion about run-time error when OP accessed > uninitialized memory. OP complained that C++ compiler (gcc) > could not detect this even though its warning level was set to > highest] > > You seem to be taking the opinion that compilers should > > catch all undefined behavior. C++ is not Java. C++'s stated > > primary design goals include > > - runtime performance comparable with assembly > > - don't pay for what you don't use > > - portable > > - easy to write code / programmer productivity (with less relative > > emphasis on this one IMHO) > > With these design goals in mind, it is not reasonable to > > expect a compiler to catch all possible undefined behavior > > or errors. To do that would necessarily restrict the > > language so that it's less comparable to assembly in speed > > and/or you start paying for things you don't use. That's not strictly true. Both the C and the C++ standards were designed so that all undefined behavior can be caught. Sometimes at a significant price, which means that very few compilers do so. But there have been some (CenterLine, I think), and of course, tools like Purify and valgrind catch a lot (but not all) of the undefined behavior (without rendering the implementation non-conform). > > In the C and C++ community, the assumption is that the > > programmer knows what he's doing, and with that assumption, > > you can (relatively) easily write really fast and portable > > code. > Just to add my two cents: > 1. C++ lets you do everything, so chances are not bad that you > can go beyond your depth. In contrast to this, JAVA restricts > your abilities (no messing around with pointers), which makes > your code inherently safer. That's provably false. Java seriously restricts what you can do, to the point of not allowing you to write safe code (for a sufficiently high enough level of "safe"). Basically, C++ doesn't to anything by default to provide safety, but allows you (or your organization) to take whatever steps are needed for the level of safety you need. Java imposes a very specific level of safety. If it's adequate, fine---you don't have to do anything else. If it's not, you're stuck, because there's nothing else you can do. (The specific level Java imposes is NOT adequate for most of what I do.) > I think both are inferior to programming languages like Ada95. From what I've heard of it, you're probably right. But I've never had the occasion to really use it, to be sure. > Ada has a real type system (something that neither C++ nor > JAVA has) and will perform zounds of checks (it is the only > language I know that handles integer overflows). Again, C++ leaves behavior in case of overflow of signed integral types or floating point types "undefined behavior". So an implementation can perform all of the checks it wants. The problem is that most implementations defined the behavior much like Java does, which is useless (at least for "safe" software). And the real problem is that most programmers accept such implementations, and consider them normal---that most programmers don't care about safety. (I've written C code in the past which verified integral overflow, and I could do it in Java or C++. But such code will never be as efficient as if the compiler did it.) > Since these checks give you a lot of performance penalties, Are you sure of that. I seem to recall reading that in typical programs, a decent compiler is able to eliminate 90% of the checks entirely. And if the compiler is generating the code, it's one extra instruction per operation for the checks which cannot be eliminated (at least on the machines I'm familiar with). Not a killer for most applications. > you have to provide additional information about which checks > can be omitted. This is maybe the major difference between C++ > and Ada95: Out of the box C++ provides few checks in favor of > speed, whereas Ada95 has all checks turned on. So C++ you have > to OPT-IN for run-time checks, Ada95 has the converse OPT-OUT > philosophy. Needless to say, nobody uses Ada95 except the > Bundeswehr in Germany (AFAIK). Most C++ compilers don't allow you to opt-in, even though it's the only reasonable option for most software. > 2. Maybe even such fancy languages like Ada cannot reliably > detect memory aliasing issues because it may be the case that > this task is Turing hard. I'm not sure which aliasing issues you're concerned about, but a lot of languages I've seen used in the past don't allow you to take the address of a variable (so pointers can only come from dynamic allocation), use garbage collection (so a pointer can never point to a non-allocated object---or worse, memory that has since been allocated to a different object), and don't support pointer arithmetic, so pointers can't point into the middle of objects. Under such conditions, aliasing isn't a difficult problem. > I haven't had time to think about it in detail, but I think > that you could reduce the HALTING problem to the problem of > accessing uninitialized memory through aliasing. This would > explain why the compiler industry didn't come up with a > "decent" compiler: It just may be that detecting _ALL_ such > errors is simply impossible (which doesn't mean that there may > be a good heuristic algorithm for detecting most of the > obvious bugs). I further assume that most cases where you get > UB are also due to the impossibiliy to check for such cases > algorithmically. Compile time or runtime. The C++ standard certainly allows "fat" pointers, which contain enough information for the runtime to be able to detect all undefined behavior. Such an implementation would run slower; an even greater problem is that it wouldn't be compatible with the defined ABI of most platforms. -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
| | #29 |
|
Posts: n/a Hébergeur: | On Jul 10, 9:01am, jacob navia <ja...@jacob.remcomp.fr> wrote: > On 10 juil, 11:57, Ian Collins <ian-n...@hotmail.com> wrote: > > > > > Don't hack. > > > -- > > Ian Collins > > Sure sure. How ful. This is a HUGE code base of MB and MB of > C++. I did not write this code. It is my job to make it work, that's > all. > > Obviously I am being blamed for asking a question, since asking > questions is obviously a NO NO here. > > (If you ask a question it means you do not know everything, > contrary to the gurus here) > > "Don't hack" > > And how can I know if in those MBs of code there is a hack? > > That was my question. Now, please answer THAT, and if you can't > I hope you can at least keep your mouth SHUT! The job of the C++ compiler is simply to compile your code. Yes, it could in theory do all the things you want it to do, because sure there have been techniques invented that do such things. But might I suggest your company invest in a static code analysis tool? While a C+ + *compiler's* job is to compile your code according to the standard, a static code analysis tool's purpose is exactly what you seem to be looking for. So there's really no point in GCC attempting to add these kind of features because they take programmer time away from actually making the compiler more robust, stronger, producing faster code, and confirming to the evolving standard. While the static code analysis writers, on the other hand, have all the time in the world to do exactly what you're looking for. There are a number of really good ones available, possibly even some free ones. I would have a look on Google for some if I were you. |
|
| | #30 |
|
Posts: n/a Hébergeur: | On Jul 11, 7:27am, jacob navia <ja...@nospam.org> wrote: > gcc (and this is a feature of course, not a bug) generates code that it > is impossible to follow with -O2 or -O3. Then, the gcc compiler > considers that it has the right to generate code that reads from > an uninitialized memory location without even caring to see if they > could (at least) emit a warning. Warnings are emitted at compile time. Reads from uninitialized memory happen at run time. Doing a complete static data flow analysis of your program to detect this is not an easy problem in the general case. Use a combination of static & dynamic code analysis tools. Honestly, you could have detected the exact location of the error in about 5 minutes using Valgrind. Although you then would have been scratching your head, wondering why the heck that was uninitialized in the first place. Then a static analysis tool would have answered that for you in about 5 minutes. Make it part of your build process to fix all the code analysis warnings in your codebase once a week from now on, much like you do to fix all GCC warnings. GCC's a compiler, software development isn't a one-tool job. You need debuggers, profilers, static analysis, dynamic analysis, source code control, etc. I realize you're frustrated spending 2 weeks fixing this bug which you think is a stupid bug and should never happened in the first place. But hey, you learned an important lesson. Don't let it happen in the first place next time. Use the right tool for the job. |
|
| | #31 |
|
Posts: n/a Hébergeur: | Anand Hariharan <mailto.anand.hariharan@gmail.com> writes: > On Jul 10, 5:05am, p...@informatimago.com (Pascal J. Bourguignon) > wrote: > (...) >> >> Notice that of the same sort of bug that should be checked at run-time >> are the array overflows and invalid pointers dereferences. The C and >> C++ standard explicitely say that derefering a pointer outside of its >> pointed array is undefined, even holding a pointer outside of its >> array limits (plus 1) is undefined... >> > > Trying to read the value of an uninitialised variable results in UB as > well. > > >> char a[5]; >> char* p=a; // valid >> p+=4; // valid >> *p; // valid >> p++; // valid >> *p; // undefined >> p++; // undefined >> > > The first *p that you state as valid results in undefined behaviour > because 'a' is not initialised. Oops! Make it: char a[5]="abcd"; -- __Pascal Bourguignon__ |
|
| | #32 |
|
Posts: n/a Hébergeur: | Joshua Maurice <joshuamaurice@gmail.com> writes: > On Jul 10, 3:05am, p...@informatimago.com (Pascal J. Bourguignon) > wrote: >> jacob navia <ja...@nospam.org> writes: >> > I thought there could be a book with *advanced* C++ debugging but a >> > Google search, then an Amazon search yielded nothing >> > but books for beginners or user manuals of Visual C++ debugger >> > written in a book form. >> >> > Is there a combination of gcc warnings (that is NOT included in Wall >> > since we already have that) that could be useful here? >> >> I wouldn't hold my breadth. >> >> > Is there a tool somewhere that could diagnose this problem? >> >> It's done by the Zeta-C compiler (since the target is the >> LispMachine). Of course, today it might be easier to build a time >> machine than to find a LispMachine with the Zeta-C compiler, and >> anyways, it doesn't solve the problem of C++. >> >> Perhaps one of the C/C++ interpreters are doing this type check. Try >> them. >> >> C INTERPRETERS: >> CINT -http://root.cern.ch/root/Cint.html >> EiC -http://eic.sourceforge.net/ >> Ch -http://www.softintegration.com >> [ MPC (Multi-Platform C -> Java compiler) -http://www.axiomsol.com] >> >> Otherwise, your best chance would be to patch them, or gcc (or >> lcc-win32), to generate tagged data and implement run-time type >> checks. >> >> Notice that of the same sort of bug that should be checked at run-time >> are the array overflows and invalid pointers dereferences. The C and >> C++ standard explicitely say that derefering a pointer outside of its >> pointed array is undefined, even holding a pointer outside of its >> array limits (plus 1) is undefined... > > [snip] > >> The problem is that C compiler writers don't bother writting the >> run-time checks that would detect these bugs, much less doing the type >> inference that would be needed to detecht a small number of them at >> compilation-time. > > You seem to be taking the opinion that compilers should catch all > undefined behavior. Not necessarily ALL the implementations (compilers or interpreters), but there should be such implementations, and those should be the implementation used most of the time, because most of the time, C++ programs are mere application programs that would benefit much more from run-time checking than from fast instructions (the more so on modern processors, where it's pointless to go fast in the processor, since you always are waiting on the RAM). > C++ is not Java. C++'s stated primary design goals > include > - runtime performance comparable with assembly For most programs, we don't care about the speed. > - don't pay for what you don't use I wish you'd paid for the uncaught bugs left in executables that affect the users. > [...] > - easy to write code / programmer productivity (with less relative > emphasis on this one IMHO) Programmers would be more productive if the implementations ed to catch bugs at run-time. > With these design goals in mind, it is not reasonable to expect a > compiler to catch all possible undefined behavior or errors. Implementations of other programming languages are able to do so, why not implementations of C++? It's perfectly reasonable to expect it, and as a user of C++, I'd rather use such an implementation for 100% of my C++ development, and 99% of my C++ program deployment. > To do > that would necessarily restrict the language so that it's less > comparable to assembly in speed and/or you start paying for things you > don't use. Not at all, the restrictions are already in the language. (Well, s/undefined behavior/and error should be signaled a compilation time or thrown at run-time/). > In the C and C++ community, the assumption is that the programmer > knows what he's doing, and with that assumption, you can (relatively) > easily write really fast and portable code. But nobody need really fast code. What we need is correct code, and code that detects automatically when it goes awry, instead of going on with invalid data in the memory, or worse, viruses and worms. > That someone hasn't written a "debugging" compiler which catches all > possible violations of the standard, as a debugging tool only, is > indeed a shame if true. Ah! You're conceding my point. Thank you. > However, Valgrind comes to mind as useful tool > in this area. But it's far from what we could expect. > Also, various versions MSVC do have optional runtime > bounds checking and other runtime checking. Good! Unfortunately on unix I know of no compiler implementing run-time checks (only interpreters do, unfortunately, C++ interpreters have too many restrictions on the language implemented so they're generally useless). > Finally, C interpreters > can catch all such misuse which occurs at runtime, the existence of > which you reference in your post. Thus, it appears the tools which you > bemoan do not exist, do indeed exist, and thus I am confused by your > self contradictions. AFAIK, there's no production-level implementation of C++ on unix (Linux) providing run-time checks for undefined behavior. The interpreters who indeed provide run-time checks, don't implement the full C++ language, so they're not usable on real programs. (eg. underC, http://home.mweb.co.za/sd/sdonovan/underc.html doesn't implement multiple-inheritance). Basically, what we'd like is an option of gcc/g++ (independent of the optimization level) which would let you deploy programs with full run-time checks. No buffer overflow would go undetected in an executable compiled with that option. -- __Pascal Bourguignon__ |
|
| | #33 |
|
Posts: n/a Hébergeur: | Joshua Maurice <joshuamaurice@gmail.com> writes: > On Jul 10, 5:51pm, Anand Hariharan <mailto.anand.hariha...@gmail.com> > wrote: >> On Jul 10, 5:54 pm, Joshua Maurice <joshuamaur...@gmail.com> wrote: >> > With these design goals in mind, it is not reasonable to expect a >> > compiler to catch all possible undefined behavior or errors. To do >> > that would necessarily restrict the language so that it's less >> > comparable to assembly in speed and/or you start paying for things you >> > don't use. >> >> You seem to be under the impression that the compiler "catching >> undefined behaviour" is synonymous with either *disallowing* undefined >> behaviour or imposing a runtime penalty to track them. OP clearly >> indicated that he only wishes the compiler to indicate to him that he >> might be doing something that leads to UB. > > Within C++ as the language rules stand, determining at compile-time if > the program can give undefined behavior through an aliasing violation > is in general undecidable, equivalent to the halting problem. This is the reason why it has to be done at run-time, when it occurs. > I did not claim such "catching undefined behavior" and "disallowing > certain constructs andor runtime checks" are not synonymous. However, > they are related. > > I believe I was correct and reasonable when I interpreted that the OP > was asking for a compiler which caught all bad aliasing, and I believe > I was correct and reasonable when I stated that doing so is impossible > without disallowing certain kinds of casting or imposing additional > runtime checks (both of which are contrary to the design goals of C+ > +). Notice that the design goals of Common Lisp are the same. However, most Common Lisp implementation implement run-time checks most of the time. (It is possible to disable most of the run-time checks in speed critical parts). > I noted that it's quite reasonable and desirable for a "debugging > compiler" to add runtime checks to catch all such aliasing errors in > development. I disagree with the overall theme of your reply: that I > was incorrect in my statement of fact or that I was incorrect in my > interpretation of the OP's desire to have all aliasing violations > caught. -- __Pascal Bourguignon__ |
|
| | #34 |
|
Posts: n/a Hébergeur: | jacob navia <jacob@nospam.org> writes: > [...] > How are the maintainers supposed to know that? By knowing the language, indeed. Some reading between the lines has to be done, but still, it's well known that these constructs have no standard defined behavior. > [...] > > You are just saying the obvious: > > C++ is not maintainable without huge efforts. > > It is very easy to laugh at the maintenance programmers here. They > are just stupid of course, since if they weren't, they wouldn't be > in maintenance of course! We may also laugh at the managers who choosed to develop the software in C++ in the first place, when better programming languages existed, exist, and will exist. > gcc (and this is a feature of course, not a bug) generates code that it > is impossible to follow with -O2 or -O3. Yes, but it's FAST! :-) > Then, the gcc compiler considers that it has the right to generate > code that reads from an uninitialized memory location without even > caring to see if they could (at least) emit a warning. Yes, the C++ standard explicitely allows it to do so. Bad standard, change standard. That said, I don't know a lot of language whose standard doesn't give a sizeable amount of leaway to the implementations. Even Common Lisp leaves a lot of freedom to the implementations, so you have a lot of constructs that are implementation dependant. When you want to write portable code, you have to be careful not to use implementation dependant (including option dependant) constructs. Yours was one. -- __Pascal Bourguignon__ |
|
| | #35 |
|
Posts: n/a Hébergeur: | James Kanze <james.kanze@gmail.com> writes: >> Since these checks give you a lot of performance penalties, > > Are you sure of that. I seem to recall reading that in typical > programs, a decent compiler is able to eliminate 90% of the > checks entirely. And if the compiler is generating the code, > it's one extra instruction per operation for the checks which > cannot be eliminated (at least on the machines I'm familiar > with). Not a killer for most applications. Indeed. Modern processors (eg. as old as 680x0) provide software traps to catch overflow/undeflow that used to cost very little, and that cost nothing with pipelined processors, when the trap is not taken. >> 2. Maybe even such fancy languages like Ada cannot reliably >> detect memory aliasing issues because it may be the case that >> this task is Turing hard. > > I'm not sure which aliasing issues you're concerned about, but a > lot of languages I've seen used in the past don't allow you to > take the address of a variable (so pointers can only come from > dynamic allocation), use garbage collection (so a pointer can > never point to a non-allocated object---or worse, memory that > has since been allocated to a different object), and don't > support pointer arithmetic, so pointers can't point into the > middle of objects. Under such conditions, aliasing isn't > a difficult problem. > >> I haven't had time to think about it in detail, but I think >> that you could reduce the HALTING problem to the problem of >> accessing uninitialized memory through aliasing. This would >> explain why the compiler industry didn't come up with a >> "decent" compiler: It just may be that detecting _ALL_ such >> errors is simply impossible (which doesn't mean that there may >> be a good heuristic algorithm for detecting most of the >> obvious bugs). I further assume that most cases where you get >> UB are also due to the impossibiliy to check for such cases >> algorithmically. > > Compile time or runtime. The C++ standard certainly allows > "fat" pointers, which contain enough information for the runtime > to be able to detect all undefined behavior. Such an > implementation would run slower; an even greater problem is that > it wouldn't be compatible with the defined ABI of most > platforms. Well, you would have to recompile the libraries, but since most if not all libraries are written in C or C++, there would be no real difficulty. (Common Lisp has not the same luck here). -- __Pascal Bourguignon__ |
|
| | #36 |
|
Posts: n/a Hébergeur: | On Jul 15, 10:39 am, p...@informatimago.com (Pascal J. Bourguignon) wrote: > Joshua Maurice <joshuamaur...@gmail.com> writes: > > On Jul 10, 3:05 am, p...@informatimago.com (Pascal J. Bourguignon) > > wrote: > > [snip] > >> The problem is that C compiler writers don't bother > >> writting the run-time checks that would detect these bugs, > >> much less doing the type inference that would be needed to > >> detecht a small number of them at compilation-time. > > You seem to be taking the opinion that compilers should > > catch all undefined behavior. > Not necessarily ALL the implementations (compilers or > interpreters), but there should be such implementations, and > those should be the implementation used most of the time, > because most of the time, C++ programs are mere application > programs that would benefit much more from run-time checking > than from fast instructions (the more so on modern processors, > where it's pointless to go fast in the processor, since you > always are waiting on the RAM). I think that there are some implementations. At least in the past, CenterLine caught most cases of undefined behavior. I don't know what its current status is, but it is still being sold. (http://www.ics.com/products/centerline/objectcenter/, for more information.) I agree with you that such a compiler should be the default and usually used compiler. I have the impression, however, that we are in a very small minority---at any rate, I don't have the impression that CenterLine is a market leader. (ICS, which owns it, seems to push its GUI expertise and products considerably more.) [...] > > With these design goals in mind, it is not reasonable to > > expect a compiler to catch all possible undefined behavior > > or errors. > Implementations of other programming languages are able to do > so, why not implementations of C++? It's perfectly reasonable > to expect it, and as a user of C++, I'd rather use such an > implementation for 100% of my C++ development, and 99% of my > C++ program deployment. Implementations of C++ are capable of doing a lot more than they do. Apparently, the market doesn't want it. (Should we conclude that C++ programmers don't care about quality, or programmer productivity?) [...] > > Also, various versions MSVC do have optional runtime bounds > > checking and other runtime checking. > Good! But only in the standard library, I think. > Unfortunately on unix I know of no compiler implementing > run-time checks (only interpreters do, unfortunately, C++ > interpreters have too many restrictions on the language > implemented so they're generally useless). My impression is that g++ and VC++ are about equal with regards to verifications. (VC++ does emit a lot of warnings about using functions which don't, or can't verify, e.g. strcpy and such.) [...] > Basically, what we'd like is an option of gcc/g++ (independent > of the optimization level) which would let you deploy programs > with full run-time checks. No buffer overflow would go > undetected in an executable compiled with that option. Arrays in C are very poorly designed, and C++ has inherited this. In order to do full run-time checking, you need fat pointers. Which not only slows the code down considerably, but also breaks the ABI. If you rigorously avoid C style arrays, and only use std::vector, g++ does run-time check. (But as soon as you do something like &v[i], all bets are off with regards to the resulting pointer.) -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
| | #37 |
|
Posts: n/a Hébergeur: | pjb@informatimago.com (Pascal J. Bourguignon) writes: > Joshua Maurice <joshuamaurice@gmail.com> writes: > >> C++'s stated primary design goals include >> - runtime performance comparable with assembly > > For most programs, we don't care about the speed. And for programs that do care about speed, they still have a lot of spare time to do checks: http://www.cs.virginia.edu/papers/Hi...all-wulf94.pdf -- __Pascal Bourguignon__ |
|
| | #38 |
|
Posts: n/a Hébergeur: | Stuart Redmann wrote: > On 11 Jul., 00:54, Joshua Maurice <joshuamaur...@gmail.com> wrote: > > Just to add my two cents: > 1. C++ lets you do everything, so chances are not bad that you can go > beyond your depth. In contrast to this, JAVA restricts your abilities > (no messing around with pointers), which makes your code inherently > safer. I think both are inferior to programming languages like Ada95. > Ada has a real type system (something that neither C++ nor JAVA has) > and will perform zounds of checks (it is the only language I know that > handles integer overflows). Since these checks give you a lot of > performance penalties, you have to provide additional information > about which checks can be omitted. Well, I am no expert on Ada, but I had a look on Ada 2005 when searching for other languages to learn and wrote only some simple programs. I finally changed to Haskell and Ocaml just to learn some new principles of programming. Anyway the Ada people claim, that a lot of these checks can be optimised out by the compiler and the remaining ones are rather inexpensive. > This is maybe the major difference > between C++ and Ada95: Out of the box C++ provides few checks in favor > of speed, whereas Ada95 has all checks turned on. So C++ you have to > OPT-IN for run-time checks, Ada95 has the converse OPT-OUT philosophy. > Needless to say, nobody uses Ada95 except the Bundeswehr in Germany > (AFAIK). Even that is not quite true. Have a look at: http://www.seas.gwu.edu/~mfeldman/ad...t-summary.html Also, comp.lang.ada is quite active and there is even a new language for the dotnet framework called A# which is an Ada derivate (like F# is an ML derivate). > > 2. Maybe even such fancy languages like Ada cannot reliably detect > memory aliasing issues because it may be the case that this task is > Turing hard. Ok, my information here is very very unprecise, because I just skimmed over that chapters, but in Ada 2005 there is some construct where you have to declare e.g. a pointer to Integer with the keyword ALIASING when it should have the possibility to be set to already allocated memory, which allows the compiler to detect such things. I am absolutely not sure, how safe this is or what the compiler allows/disallows here, anyone more familiar with Ada could probably explain. > Cheer up, you have one of the worst jobs of the world of programming: > Inheriting code for your predecessor (some people say that this is > what object orientation is all about ;-), and having to find the bugs > in this code. Practically noone will give you credit for this, you're > more or less just a scape-goat. I second that. I did a lot of maintenance/enhancements to existing C++ systems which sometimes leads you to ludicrous laughs and sometimes to deep depression ![]() > Personally, I have made little else > than re-write code that has been written by physicists (which should > be prohibited to writing code by law :-) for the last ten years. Quite similar here: develop a System in C++, give it out to about 20 companies to develop/extend/evolve this system, where it uses some very old libraries/methods which even prevent you from using e.g. valgrind or even gdb in some cases, feed all of this into the main line and then give it to poor developers to go on bug-hunt ![]() Not to mention, that the main reason, why it is used is more of a political issue... One of our favourite discussions between the developers in my departement is about bashing this system... lg, Michael |
|
| | #39 |
|
Posts: n/a Hébergeur: | On 14 July, 17:09, James Kanze <james.ka...@gmail.com> wrote: > On Jul 14, 10:40 am, Stuart Redmann <DerTop...@web.de> wrote: > > On 11 Jul., 00:54, Joshua Maurice <joshuamaur...@gmail.com> wrote: > > [snipped discussion about run-time error when OP accessed > > uninitialized memory. OP complained that C++ compiler (gcc) > > could not detect this even though its warning level was set to > > highest] > > > > You seem to be taking the opinion that compilers should > > > catch all undefined behavior. C++ is not Java. C++'s stated > > > primary design goals include > > > - runtime performance comparable with assembly > > > - don't pay for what you don't use > > > - portable > > > - easy to write code / programmer productivity (with less relative > > > emphasis on this one IMHO) > > > With these design goals in mind, it is not reasonable to > > > expect a compiler to catch all possible undefined behavior > > > or errors. To do that would necessarily restrict the > > > language so that it's less comparable to assembly in speed > > > and/or you start paying for things you don't use. > > That's not strictly true. Both the C and the C++ standards were > designed so that all undefined behavior can be caught. really? Where does it say that? Do you mean at compile time or at run-time? I'd always thought about half of UB was in the spec precisely because it was too hard to detect. The other half was hardware stuff things like what the modulo operator does with negative numbers gets() > Sometimes at a significant price, which means that very few > compilers do so. But there have been some (CenterLine, I > think), and of course, tools like Purify and valgrind catch a > lot (but not all) of the undefined behavior (without rendering > the implementation non-conform). <snip> > > I haven't had time to think about it in detail, but I think > > that you could reduce the HALTING problem to the problem of > > accessing uninitialized memory through aliasing. ITYM detecting the access of uninitialized memory through aliasing at compile time is equivalent to the Halting Problem. > > This would > > explain why the compiler industry didn't come up with a > > "decent" compiler: It just may be that detecting _ALL_ such > > errors is simply impossible (which doesn't mean that there may > > be a good heuristic algorithm for detecting most of the > > obvious bugs). I further assume that most cases where you get > > UB are also due to the impossibiliy to check for such cases > > algorithmically. > > Compile time or runtime. The C++ standard certainly allows > "fat" pointers, which contain enough information for the runtime > to be able to detect all undefined behavior. Such an > implementation would run slower; an even greater problem is that > it wouldn't be compatible with the defined ABI of most > platforms. I can't quite work out how to break a fat-pointer implementation but can't you do some very nasty things with printf("%p") and scanf ("%p")? |
|
| | #40 |
|
Posts: n/a Hébergeur: | Nick Keighley wrote: > > I'd always thought about half of UB was in the spec precisely because > it was too hard to detect. The other half was hardware stuff things > like > what the modulo operator does with negative numbers That's not undefined behavior. It's implementation defined. -- Pete Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The Standard C++ Library Extensions: a Tutorial and Reference" (www.petebecker.com/tr1book) |
|
| | #41 |
|
Posts: n/a Hébergeur: | In article <026627ea-6afc-457e-9a2f-399baf9976f8 @c36g2000yqn.googlegroups.com>, james.kanze@gmail.com says... > > On Jul 15, 10:39 am, p...@informatimago.com (Pascal J. Bourguignon) > wrote: > > Joshua Maurice <joshuamaur...@gmail.com> writes: [ ... ] > [...] > > > Also, various versions MSVC do have optional runtime bounds > > > checking and other runtime checking. > > > Good! > > But only in the standard library, I think. Not so -- recent versions have flags to tell it to include runtime checks in your code. A short description is available at: http://msdn.microsoft.com/en-us/libr...8VS.80%29.aspx [ ... ] > Arrays in C are very poorly designed, and C++ has inherited this. > In order to do full run-time checking, you need fat pointers. > Which not only slows the code down considerably, but also breaks > the ABI. If you rigorously avoid C style arrays, and only use > std::vector, g++ does run-time check. (But as soon as you do > something like &v[i], all bets are off with regards to the > resulting pointer.) Interestingly, the run-time checks provided by MS VC++ have almost exactly the same limitation in one respect -- they can track (to a degree) whether you use uninitialized variables, but taking the address is treated as equivalent to initialization. -- Later, Jerry. |
|
| | #42 |
|
Posts: n/a Hébergeur: | On Jul 15, 1:39am, p...@informatimago.com (Pascal J. Bourguignon) wrote: > Joshua Maurice <joshuamaur...@gmail.com> writes: > > C++ is not Java. C++'s stated primary design goals > > include > > - runtime performance comparable with assembly > > For most programs, we don't care about the speed. > > > - don't pay for what you don't use > > I wish you'd paid for the uncaught bugs left in executables that > affect the users. > > > [...] > > - easy to write code / programmer productivity (with less relative > > emphasis on this one IMHO) > > Programmers would be more productive if the implementations ed to > catch bugs at run-time. I full heartily agree that current C++ compilers make me sad. They make me sad for lack of standard compliance (some recent versions of MSVC don't support covariant return types with multiple inheritance, all compilers have bugs: http://www.cs.utah.edu/~regehr/paper...8-preprint.pdf etc.) and lack of developer-focused tools. I would very much want every compiler out there to use "fat" pointers and other techniques to catch all undefined behavior, either at compile time or runtime. I also very much want this to be entirely optional, and for it to be expressly stated that no "good" C++ program should depend upon such checks; they should exist only as "terminate the process" asserts only. > For most programs, we don't care about the speed. Agreed, and with the current state of the C++ industry, C++ is not the best language for every situation. Perhaps Java is be more useful for most programs. I very much want C++ to remain focused on runtime performance. However, \at least\ for developing purposes, I would also very much like \optional\ Java-like runtime checks to catch all undefined behavior. Unfortunately, it's impractical because it would break all platform ABIs, and it requires compiler writers to write such things which apparently isn't going to happen anytime soon. |
|
| | #43 |
|
Posts: n/a Hébergeur: | On Jul 15, 2:07am, James Kanze <james.ka...@gmail.com> wrote: > On Jul 15, 10:39 am, p...@informatimago.com (Pascal J. Bourguignon) > wrote: > > > > > > > Joshua Maurice <joshuamaur...@gmail.com> writes: > > > On Jul 10, 3:05 am, p...@informatimago.com (Pascal J. Bourguignon) > > > wrote: > > > [snip] > > >> The problem is that C compiler writers don't bother > > >> writting the run-time checks that would detect these bugs, > > >> much less doing the type inference that would be needed to > > >> detecht a small number of them at compilation-time. > > > You seem to be taking the opinion that compilers should > > > catch all undefined behavior. > > Not necessarily ALL the implementations (compilers or > > interpreters), but there should be such implementations, and > > those should be the implementation used most of the time, > > because most of the time, C++ programs are mere application > > programs that would benefit much more from run-time checking > > than from fast instructions (the more so on modern processors, > > where it's pointless to go fast in the processor, since you > > always are waiting on the RAM). > > I think that there are some implementations. At least in the > past, CenterLine caught most cases of undefined behavior. I > don't know what its current status is, but it is still being > sold. (http://www.ics.com/products/centerline/objectcenter/, > for more information.) > > I agree with you that such a compiler should be the default and > usually used compiler. I have the impression, however, that we > are in a very small minority---at any rate, I don't have the > impression that CenterLine is a market leader. (ICS, which owns > it, seems to push its GUI expertise and products considerably > more.) > > [...] > > > > With these design goals in mind, it is not reasonable to > > > expect a compiler to catch all possible undefined behavior > > > or errors. > > Implementations of other programming languages are able to do > > so, why not implementations of C++? It's perfectly reasonable > > to expect it, and as a user of C++, I'd rather use such an > > implementation for 100% of my C++ development, and 99% of my > > C++ program deployment. > > Implementations of C++ are capable of doing a lot more than they > do. Apparently, the market doesn't want it. My take is that most C++ compiler vendors were/are attempting to ride 20th century business models. They have not adapted to an on line model and what worked well for decades is now tanking. I've said it before, but I think there are only two C++ compilers with minor on line support. Comeau hasn't made much progress in it's on line support in years. They work on adding new functionality to their existing products, but not, from what I can tell, in reworking their products to beef up their on line support. There are some dinosaurs out there company-wise that are being punished now for not understanding the times ten years ago, let alone today. Your remark about reading what the market wants is related to on line products as well. In the past with very limited feedback, vendors have to try to figure out what they should do next. With an on line approach there's much more concrete information on which to base product development decisions. > (Should we > conclude that C++ programmers don't care about quality, or > programmer productivity?) Some programmers care primarily about money and only about quality because it may affect how much money they make. I'm thinking of that Russian guy who may have stolen a bunch of software from Goldman Sachs. Brian Wood Ebenezer Enterprises www.webEbenezer.net |
|
| | #44 |
|
Posts: n/a Hébergeur: | On Jul 15, 3:18 pm, Nick Keighley <nick_keighley_nos...@hotmail.com> wrote: > On 14 July, 17:09, James Kanze <james.ka...@gmail.com> wrote: > > On Jul 14, 10:40 am, Stuart Redmann <DerTop...@web.de> wrote: > > > On 11 Jul., 00:54, Joshua Maurice <joshuamaur...@gmail.com> wrote: > > > [snipped discussion about run-time error when OP accessed > > > uninitialized memory. OP complained that C++ compiler (gcc) > > > could not detect this even though its warning level was set to > > > highest] > > > > You seem to be taking the opinion that compilers should > > > > catch all undefined behavior. C++ is not Java. C++'s stated > > > > primary design goals include > > > > - runtime performance comparable with assembly > > > > - don't pay for what you don't use > > > > - portable > > > > - easy to write code / programmer productivity (with less relative > > > > emphasis on this one IMHO) > > > > With these design goals in mind, it is not reasonable to > > > > expect a compiler to catch all possible undefined behavior > > > > or errors. To do that would necessarily restrict the > > > > language so that it's less comparable to assembly in speed > > > > and/or you start paying for things you don't use. > > That's not strictly true. Both the C and the C++ standards > > were designed so that all undefined behavior can be caught. > really? Where does it say that? Do you mean at compile time or > at run-time? At run-time, at the latest. (I think that there is some which can't be detected at compile time. But probably a lot less than one might think---compilers have gotten quite good at tracing intermodular code flow.) And it's scattered throughout the standard. Mostly in the form of "undefined behavior"---the behavior is undefined precisely so that a checking implementation can trap it. > I'd always thought about half of UB was in the spec precisely > because it was too hard to detect. Too hard, no. Too expensive, perhaps: to catch all pointer violations, you need "fat" pointers---each pointer contains a current address, plus the limits, each modification of the pointer value verifies that the current address stays in the limits, and each access through the pointer verifies that it isn't using the end pointer (and that the pointer isn't null, but most hardware traps this already today). Of course, a good compiler could eliminate a certain number of these checks, or at least hoist them outside of a loop. But I don't think it could easily avoid the fact that the size of a pointer is multiplied by three, which makes things like copying significantly more expensive, and can have very negative effects on locality. > The other half was hardware stuff things like what the modulo > operator does with negative numbers That's unspecified, not undefined behavior. > gets() Takes a pointer. If the pointer contains the bounds, then it can easily check. > <snip> > > > I haven't had time to think about it in detail, but I > > > think that you could reduce the HALTING problem to the > > > problem of accessing uninitialized memory through > > > aliasing. > ITYM detecting the access of uninitialized memory through > aliasing at compile time is equivalent to the Halting Problem. > > > This would explain why the compiler industry didn't come > > > up with a "decent" compiler: It just may be that detecting > > > _ALL_ such errors is simply impossible (which doesn't mean > > > that there may be a good heuristic algorithm for detecting > > > most of the obvious bugs). I further assume that most > > > cases where you get UB are also due to the impossibiliy to > > > check for such cases algorithmically. > > Compile time or runtime. The C++ standard certainly allows > > "fat" pointers, which contain enough information for the > > runtime to be able to detect all undefined behavior. Such > > an implementation would run slower; an even greater problem > > is that it wouldn't be compatible with the defined ABI of > > most platforms. > I can't quite work out how to break a fat-pointer > implementation but can't you do some very nasty things with > printf("%p") and scanf ("%p")? Given that the standard makes these implementation defined, I don't think so. It might make detecting undefined behavior expensive, however. About the only way I think that an implementation could determine that the value read by scanf("%p") is "a value converted eariler during the same program execution" is by saving all of the pointers output by printf("%p") somewhere. (Inputting any other value is undefined behavior.) -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
| | #45 |
|
Posts: n/a Hébergeur: | On Jul 15, 9:18 pm, Jerry Coffin <jerryvcof...@yahoo.com> wrote: > In article <026627ea-6afc-457e-9a2f-399baf9976f8 > @c36g2000yqn.googlegroups.com>, james.ka...@gmail.com says... > > On Jul 15, 10:39 am, p...@informatimago.com (Pascal J. Bourguignon) > > wrote: > > > Joshua Maurice <joshuamaur...@gmail.com> writes: > [ ... ] > > [...] > > > > Also, various versions MSVC do have optional runtime bounds > > > > checking and other runtime checking. > > > Good! > > But only in the standard library, I think. > Not so -- recent versions have flags to tell it to include > runtime checks in your code. A short description is available > at: > http://msdn.microsoft.com/en-us/libr...8VS.80%29.aspx Well, it's a start, although it's still very limited. > [ ... ] > > Arrays in C are very poorly designed, and C++ has inherited > > this. In order to do full run-time checking, you need fat > > pointers. Which not only slows the code down considerably, > > but also breaks the ABI. If you rigorously avoid C style > > arrays, and only use std::vector, g++ does run-time check. > > (But as soon as you do something like &v[i], all bets are > > off with regards to the resulting pointer.) > Interestingly, the run-time checks provided by MS VC++ have > almost exactly the same limitation in one respect -- they can > track (to a degree) whether you use uninitialized variables, > but taking the address is treated as equivalent to > initialization. Which wasn't really what I was talking about. My point was that having done &v[i], you have a raw pointer, on which you can do pointer arithmetic, and access out of bounds without checking, even if the implementation checks in vector<>: perator[].But the documentation on how VC++ detects uninitialized variables did seem wierd to me. For a runtime check, I'd have just associated an additional flag somewhere, setting it when the variable was set, and checking it otherwise. Perhaps the problem is that if initialization occurs through a pointer, the compiler can't generate the code to update the flag, so if the address is taken (which would allow such initialization), it just gives up. Come to think of it, that's very likely the reason. The obvious way of being able to find the flag through the pointer would change the size or the range of the data type. And the other ways I can think of are fairly complex, and probably rather expensive in run-time. And you're right that that's sort of the same problem as with &v[i]---the use of a pointer causes the code to "loose" any associated data. -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
| | #46 |
|
Posts: n/a Hébergeur: | On Jul 15, 11:02 pm, Joshua Maurice <joshuamaur...@gmail.com> wrote: > On Jul 15, 1:39 am, p...@informatimago.com (Pascal J. Bourguignon) > wrote: [...] > I would very much want > every compiler out there to use "fat" pointers and other techniques to > catch all undefined behavior, either at compile time or runtime. I > also very much want this to be entirely optional, and for it to be > expressly stated that no "good" C++ program should depend upon such > checks; they should exist only as "terminate the process" asserts > only. The "option" is tricker than you seem to realize. Anything which changes the size of an object (e.g. fat pointers vs. normal pointers) breaks the ABI. You can't link object files compiled with different options. (Or maybe you can link, but the resulting program will just crash.) Note that this is already the case with compilers which provide "debugging" versions of std::vector and others. The debugging changes the size and the behavior of std::vector, and mixing code with and without debugging causes core dumps. > > For most programs, we don't care about the speed. > Agreed, and with the current state of the C++ industry, C++ is > not the best language for every situation. Perhaps Java is be > more useful for most programs. Only if you can accept a fairly low level of robustness. -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
| | #47 |
|
Posts: n/a Hébergeur: | Michael Oswald wrote: > Stuart Redmann wrote: >> On 11 Jul., 00:54, Joshua Maurice <joshuamaur...@gmail.com> wrote: >> >> Just to add my two cents: >> 1. C++ lets you do everything, so chances are not bad that you can >> go beyond your depth. In contrast to this, JAVA restricts your >> abilities (no messing around with pointers), which makes your code >> inherently safer. I think both are inferior to programming >> languages like Ada95. Ada has a real type system (something that >> neither C++ nor JAVA has) and will perform zounds of checks (it is >> the only language I know that handles integer overflows). Since >> these checks give you a lot of performance penalties, you have to >> provide additional information about which checks can be omitted. > > Well, I am no expert on Ada, but I had a look on Ada 2005 when > searching for other languages to learn and wrote only some simple > programs. I finally changed to Haskell and Ocaml just to learn some > new > principles of programming. > > Anyway the Ada people claim, that a lot of these checks can be > optimised out by the compiler and the remaining ones are rather > inexpensive. This was designed into the language from the beginning, so Ada arrays know their size so you can iterate over a'range. No need to range check. for i in a'range loop a(i) :=1; -- always in range end loop; Also, the index type can be a subtype restricted to the allowed range of the array type. As the index then just cannot be out of range, there is no need to check a(i). In C++ we have it differently. Bo Persson |
|
| | #48 |
|
Posts: n/a Hébergeur: | "Bo Persson" <bop@gmb.dk> writes: > Michael Oswald wrote: >> Stuart Redmann wrote: >>> On 11 Jul., 00:54, Joshua Maurice <joshuamaur...@gmail.com> wrote: >>> >>> Just to add my two cents: >>> 1. C++ lets you do everything, so chances are not bad that you can >>> go beyond your depth. In contrast to this, JAVA restricts your >>> abilities (no messing around with pointers), which makes your code >>> inherently safer. I think both are inferior to programming >>> languages like Ada95. Ada has a real type system (something that >>> neither C++ nor JAVA has) and will perform zounds of checks (it is >>> the only language I know that handles integer overflows). Since >>> these checks give you a lot of performance penalties, you have to >>> provide additional information about which checks can be omitted. >> >> Well, I am no expert on Ada, but I had a look on Ada 2005 when >> searching for other languages to learn and wrote only some simple >> programs. I finally changed to Haskell and Ocaml just to learn some >> new >> principles of programming. >> >> Anyway the Ada people claim, that a lot of these checks can be >> optimised out by the compiler and the remaining ones are rather >> inexpensive. > > This was designed into the language from the beginning, so Ada arrays > know their size so you can iterate over a'range. No need to range > check. > > for i in a'range loop > a(i) :=1; -- always in range > end loop; > > > Also, the index type can be a subtype restricted to the allowed range > of the array type. As the index then just cannot be out of range, > there is no need to check a(i). > > > In C++ we have it differently. Notice that with intensive use of classes, we could archive similar results: template <int MIN,int MAX>class Integer{ int value; public: Integer(int aValue){rangeCheck(MIN,MAX,aValue);value=aValue} // operators... }; std::vector<X> v; for(Integer<0,v.size()-1> i=0;i<v.size()-1;i++){ v[i]; // no check needed. } Ok, perhaps a more intelligent compiler and some work on the syntax is needed, but you get the idea. Now, perhaps it might be slightly easier to write: for i in a'range... -- __Pascal Bourguignon__ |
|
| | #49 |
|
Posts: n/a Hébergeur: | Pascal J. Bourguignon wrote: > "Bo Persson" <bop@gmb.dk> writes: > >> Michael Oswald wrote: >>> Stuart Redmann wrote: >>>> On 11 Jul., 00:54, Joshua Maurice <joshuamaur...@gmail.com> wrote: >>>> >>>> Just to add my two cents: >>>> 1. C++ lets you do everything, so chances are not bad that you can >>>> go beyond your depth. In contrast to this, JAVA restricts your >>>> abilities (no messing around with pointers), which makes your code >>>> inherently safer. I think both are inferior to programming >>>> languages like Ada95. Ada has a real type system (something that >>>> neither C++ nor JAVA has) and will perform zounds of checks (it is >>>> the only language I know that handles integer overflows). Since >>>> these checks give you a lot of performance penalties, you have to >>>> provide additional information about which checks can be omitted. >>> Well, I am no expert on Ada, but I had a look on Ada 2005 when >>> searching for other languages to learn and wrote only some simple >>> programs. I finally changed to Haskell and Ocaml just to learn some >>> new >>> principles of programming. >>> >>> Anyway the Ada people claim, that a lot of these checks can be >>> optimised out by the compiler and the remaining ones are rather >>> inexpensive. >> This was designed into the language from the beginning, so Ada arrays >> know their size so you can iterate over a'range. No need to range >> check. >> >> for i in a'range loop >> a(i) :=1; -- always in range >> end loop; >> >> >> Also, the index type can be a subtype restricted to the allowed range >> of the array type. As the index then just cannot be out of range, >> there is no need to check a(i). >> >> >> In C++ we have it differently. > > Notice that with intensive use of classes, we could archive similar results: > > template <int MIN,int MAX>class Integer{ > int value; > public: > Integer(int aValue){rangeCheck(MIN,MAX,aValue);value=aValue} > // operators... > }; > > std::vector<X> v; > for(Integer<0,v.size()-1> i=0;i<v.size()-1;i++){ > v[i]; // no check needed. > } Or use tr1::array and iterators. This is closer to the Ada concept of the array knowing its size. -- Ian Collins |
|
| | #50 |
|
Posts: n/a Hébergeur: | On Jul 16, 2:09am, James Kanze <james.ka...@gmail.com> wrote: > On Jul 15, 11:02 pm, Joshua Maurice <joshuamaur...@gmail.com> wrote: > > > On Jul 15, 1:39 am, p...@informatimago.com (Pascal J. Bourguignon) > > wrote: > > [...] > > > I would very much want > > every compiler out there to use "fat" pointers and other techniques to > > catch all undefined behavior, either at compile time or runtime. I > > also very much want this to be entirely optional, and for it to be > > expressly stated that no "good" C++ program should depend upon such > > checks; they should exist only as "terminate the process" asserts > > only. > > The "option" is tricker than you seem to realize. Anything > which changes the size of an object (e.g. fat pointers vs. > normal pointers) breaks the ABI. You can't link object files > compiled with different options. (Or maybe you can link, but > the resulting program will just crash.) Indeed. I mentioned exactly this in the exact same post you quote. > Note that this is already the case with compilers which provide > "debugging" versions of std::vector and others. The debugging > changes the size and the behavior of std::vector, and mixing > code with and without debugging causes core dumps. I just wish they actually caught all errors / undefined behavior in a systematic fashion instead of in the current half-hazard way. > > > For most programs, we don't care about the speed. > > Agreed, and with the current state of the C++ industry, C++ is > > not the best language for every situation. Perhaps Java is be > > more useful for most programs. > > Only if you can accept a fairly low level of robustness. This intrigues me. If you elaborate or point me to articles, I'd love to read up on this. IMHO, I could probably write an application faster in C++ and have it be "more correct" (aka less testing / bug-fixing time), but the same probably isn't true of the average developer. I'm just curious how you're defining "robustness". Are we talking real- time? Or correct in the face of errors? Stuff like how it's easier to leak file handles, other non-memory resources? Or how it's exceedingly annoying and difficult to write correct code in the face of "dispose" / "close" / "release" calls which can throw exceptions? Or are we talking about how it's impossible to write correct code in the face of asynchronous exceptions? |
|
![]() |
| Thread Tools | |
| |