Slashdot Mirror


Ultra-Stable Software Design in C++?

null_functor asks: "I need to create an ultra-stable, crash-free application in C++. Sadly, the programming language cannot be changed due to reasons of efficiency and availability of core libraries. The application can be naturally divided into several modules, such as GUI, core data structures, a persistent object storage mechanism, a distributed communication module and several core algorithms. Basically, it allows users to crunch a god-awful amount of data over several computing nodes. The application is meant to primarily run on Linux, but should be portable to Windows without much difficulty." While there's more to this, what strategies should a developer take to insure that the resulting program is as crash-free as possible? "I'm thinking of decoupling the modules physically so that, even if one crashes/becomes unstable (say, the distributed communication module encounters a segmentation fault, has a memory leak or a deadlock), the others remain alive, detect the error, and silently re-start the offending 'module'. Sure, there is no guarantee that the bug won't resurface in the module's new incarnation, but (I'm guessing!) it at least reduces the number of absolute system failures.

How can I actually implement such a decoupling? What tools (System V IPC/custom socket-based message-queue system/DCE/CORBA? my knowledge of options is embarrassingly trivial :-( ) would you suggest should be used? Ideally, I'd want the function call abstraction to be available just like in, say, Java RMI.

And while we are at it, are there any software _design patterns_ that specifically tackle the stability issue?"

690 comments

  1. You're not the first one.... by DetrimentalFiend · · Score: 4, Insightful

    I'd hate to say it, but you might want to SERIOUSLY consider managed code. You could build some of the parts in C++ if need to be, but doing it purely in C++ seems like a bad idea to me. You're asking for a silver bullet that just doesn't exist...but managed code is getting faster and can be pretty stable.

    1. Re:You're not the first one.... by destuxor · · Score: 2, Informative

      Although I've never had reason to do this myself, I've heard people recommend cross-compiling code onto a PPC or SPARC64 platform and then fuzz your program on those platforms to look for bugs that might not have shown up on x86.
      As for your question about CORBA, look into IceC++. I read about it somewhere and it sounded cool :)

    2. Re:You're not the first one.... by arkanes · · Score: 3, Informative
      I have to agree. You say it can't be changed due to efficency and core library issues, and then list a bunch of components for which there are no core libraries in C++ and which are rarely if ever CPU bound. Further, if you're asking this question then you aren't a highly experienced guru in this field and thats what you need to be to write these sort of applications in C++. Managed Code (tm), as in .NET, is not your only option but you should look at something higher level and more robust than C++. Haskell or one of the other functional languages might be a good idea.

      Test, test, test. Use test driven development if you can. Have a good test harness and use it all the time. Do the stereotypical "random input" tests. Test each and every component to destruction white-box style and then double test all your interfaces. Design by contract can help here. Use a tinderbox that runs continual builds. Maintain strict version controls. Maintain code discipline (getting rid of C++ helps here too). Realize that you probably do not (currently) have the skills to produce the kind of product you are talking about and be willing to commit the time and effort to tear up mistakes, to start over and to teach yourself. What you are attempting to do is not easy.

    3. Re:You're not the first one.... by merlin_jim · · Score: 3, Interesting

      I was going to post pretty much the same thing - managed code approaches C++ efficiency close enough that it shouldn't matter (I've seen figures of 80-95%)

      And, in visual studio .net 2005 there are built in high performance computing primitives - all the management of internode communication and logical data semaphore locking are handled by the runtime - presumably debugged and stable code...

      --
      I am disrespectful to dirt! Can you see that I am serious?!
    4. Re:You're not the first one.... by gadzook33 · · Score: 5, Insightful

      Ah, another true believer. I work heavily in both managed and unmanaged code (c/c++/c#) hybrid solutions. In my experience, a well designed C++ program is as stable as a well designed C# program. Who cares if it "crashes" if it doesn't do what you want? The worst program is one that seems to be working but is generating invalid results. Don't let anyone convince you that C# is going to provide more reliable execution. We use C# for its nice GUIs; C++ for cross-platform portability.

    5. Re:You're not the first one.... by Anonymous Coward · · Score: 1

      Ah, the first of 200 people who don't know how to do what he wants so will answer an easier question, as happens every time any kind of question about anything lower-level than Java.

      Now can anyone who can answer the question offer some advice, please? The asker isn't the only one interested in hearing from a few experts.

    6. Re:You're not the first one.... by Anonymous Coward · · Score: 0

      Wow, what stupid advice.

    7. Re:You're not the first one.... by burni · · Score: 1

      Yes, hm.. I wanted to say the same, so I follow up here instead of starting
      a seperate thread ;)

      He(null_functor) can still use java and the feature-rich api on
      the one side, and C++ on the other side, with the Java Native Interface,
      it´s both way possible,

      you(null_functor) can call the VM+Javaprogram from inside a C++ Program,
      and the other way around, calling a C/C++ Program from a Javaprogram
      inside the virtual machine
      - sun has a good easy-to-start-tutorial http://java.sun.com, with code samples
      - google("JNI Java";"Java Native Interface")

      I´ve tried out the code samples and everything works fine, ongoing from this I´ve started interfacing with the ncurses-lib for example, because java and the unicode-centric-api-functions are the easy way to create multilanguage unicode menus from XML templates, it´s just fun from my point of view ;)

      Communicating over JavaVM and native world borders shouldn´t be a big thing,
      running Java on a linux-system you have the same access than a native program,
      Pipes, Socket, ..

      RPC ;) sun-rpc :D

      jdbc for database access,

      Speed :
      it´s not 100%, but 80% mostly are enough.

      naturally I divide the programming tasks into two categories,
      soft/well-with-the-object-model and hard/bad-with-the-object-model,

      so where OOP is needfull, I use java, I´ve a dislike against object-like
      programming in C, so where a classic structured programming language
      is needed I use C,

      so you can see, Java and C for me are symbiotic lifeforms ;)

      solving the complex things with java, I´ve also the feature, that porting
      this application to other operating systems just involves some
      JNI-code alteration.

      closing words,
      read this assuming that I like java and that I´m not a neutral person, so I promote what I like and what works for me, ;) generally I use Java and C,
      and interface both sides when needed using JNI.

    8. Re:You're not the first one.... by mr_tenor · · Score: 5, Insightful

      WTF? I love Haskell as much as the next programming-language-theory fanboy, but saying "Haskell or one of the other functional languages might be a good idea." in reply to the OP strongly suggests to me that you are just making stuff up and/o are copy/pasting things that you have read elsewhere out of context

      If not, then great! Please post some references to literature which demonstrates how what you've suggested is sane and/or possible :)

    9. Re:You're not the first one.... by Iceberg1414 · · Score: 1, Insightful

      1. I don't mean to bash your idea, but unless your "modules" are seperated into seperate processes, any part of your code or libraries can affect any other part. Writing a multi-process system has it's own complexities and issues.

      And FYI, detecting hangs is a pretty hard problem.

      2. Like was said, heavily consider going to a VM langauge (Java, .NET), unless you are willing to invest a lot of extra time in testing, code review, analysis, etc.

      3. If you are going to use C++, consider using Smart Pointers, garbage collectors, etc, available for C++ at http://www.boost.org/

      4. Test early and often, and aim for full code coverage with code coverage tools. Code you don't run is code you haven't tested. Test also with memory tools such as Bounds Checker. I beleive Linux has robust gcc-enabled tools in this area also. Throw anything and everything at your code, including strange data, bad inputs, etc.

      5. Use static code analysis if possible. You will have bugs in your code, period. Historically, this generates a lot of false positives. MS VStudio 2005 Team Edition is not free, but it may be available to you through MSDN or something. This has pretty good basic analysis of common errors available through the /analyze switch. Coverity is also a better ($$$) commercial static analysis tool.

      6. Use plenty of assertions in your code

      7. Make sure you have a good crash handler setup to generate relevant crash data and hopefully semi-automatically get it back to you.

      8. Write solid unit tests WITH your code, and make sure the code is built often /w automated running of unit tests & other tests.

    10. Re:You're not the first one.... by batkiwi · · Score: 0, Troll

      So what instances do you have on hand of a C# solution working but generating invalid results which would not have occured by using C++? You made a huge inline claim without really ANY backup!

    11. Re:You're not the first one.... by logicnazi · · Score: 1

      The things that he needs are probably things like mpi or scientific computation libraries. He didn't list these libraries because they are presumably part of the core functionality and thus are all part of the core (controller) component or aren't possible to componentize (no point in restarting if this part goes bad)

      --

      If you liked this thought maybe you would find my blog nice too:

    12. Re:You're not the first one.... by Duhavid · · Score: 4, Insightful

      I read his comment as saying that C# would not guarantee
      a good result ( correctness ). And it wont.

      What the guy really needs is a great team and some decent
      process to backstop that team. Not a silver bullet.

      --
      emt 377 emt 4
    13. Re:You're not the first one.... by Anonymous Coward · · Score: 0


      From http://en.wikipedia.org/wiki/Managed_code

      Managed code is code executed by a .NET virtual machine...In a Microsoft Windows environment, all other code has come to be known as unmanaged code

      Maybe I've gotten cynical in my middle age, but it seems rather convenient that one company has the only solution to the problem.

      OK, I'll take off my tinfoil hat now...

    14. Re:You're not the first one.... by wft_rtfa · · Score: 2
      I agree. Using some higher level language that allows you to easily call C++ code would be the best choice. I believe C#, Java, python, perl... can call C++ libraries easily. I personally would use Java and C++ if your company/environment is more geared toward Linux/unix or C# and C++ if you can get away with Windows only.

      Building any complex software in unmanaged C++ can get overwelming very quickly and will require more time than Java or C# even if you're a C++ guru. You should only attempt if you are a C++ guru and have lots trusted libraries and techniques at your disposal.

      --
      :-] :0 :-> :-| :->
    15. Re:You're not the first one.... by wft_rtfa · · Score: 2, Insightful
      Don't let anyone convince you that C# is going to provide more reliable execution.

      That is very true. However, if you're not a C++ expert or a C# expert then you will get a more reliable program much quicker in C# simply because it's easier.

      --
      :-] :0 :-> :-| :->
    16. Re:You're not the first one.... by gadzook33 · · Score: 1

      Easier = More Reliable? Er...perhaps. I've found more reliable means spending time doing good design and checking that you didn't f something up. Again, we're really not talking about whether a buffer overflows here; that can be accomplished with encapsulation and non-stupid design practice.

    17. Re:You're not the first one.... by Peter+La+Casse · · Score: 2, Insightful
      I'm not an expert, but I too see lots of people missing the point, so I'll add my two cents. There are lots of comments talking about implementation techniques, and those are very good things to do, but that's implementation, not design.

      Design is about turning analysis models into implementation. Analysis models are the result of analyzing what your system needs to do; they describe what it does, not how it does it. Use some type of formal modeling language (there are several) to exhaustively describe the behavior of your system in a way that is provably consistent. Iteratively refine the formal model until you get enough detail to implement. Use tools (you might have to write some) to prove that your implementation matches the formal design model. When the design is good, use the techniques that others have mentioned to generate a rock solid implementation.

      Writing ultra-stable software is hard. Most choose not to do it. IMO it's less fun than coming up with something in your head and banging out some Python to do it, but it is possible.

    18. Re:You're not the first one.... by gadzook33 · · Score: 3, Insightful
      You made a huge inline claim without really ANY backup!
      mmm...huge inline claim. Sounds like that could lead to memory thrashing. But seriously folks, if you took the time to actually read my post (you know, left to right, top to bottom), you'll see that I never made any such claim. There is simply nothing inherent in C# that will protect you from most classes of errors. Especially the really insidious ones that A.) You don't discover until it's too late and B.) Usually are the result of bad design, not bad language. At the end of the day, C#: Not that different from C++. The rules of logic still apply.
    19. Re:You're not the first one.... by SchroedingersCat · · Score: 5, Insightful

      Here is the clue: if the code *relies* on being *managed* then the design is not stable. Well-designed system will not need a garbage collector, and poorly-designed system will not be saved by the garbage collector.

    20. Re:You're not the first one.... by wft_rtfa · · Score: 1
      Easier = More Reliable?

      I guess you didn't read my post. My point was that if you're not a C++ expert and I'm not a C# expert, I'll finish the same program a lot faster than you. You'll still be fiddling with char arrays and memory management, and I'll be done. However, if you designed it correctly as you suggested, your program could be just as reliable, probably a little faster, but it will take longer because you have to deal with more complexity when implementing your design.

      --
      :-] :0 :-> :-| :->
    21. Re:You're not the first one.... by SEAlex · · Score: 3, Informative

      The use of managed language will not necessarily result in a more stable code. Recovering form SIGSEGV by installing a POSIX handler or detecting the death of the forked child process in C++ can be done with the same ease as catching NullPointer Runtime exception in Java.

      I would agree that having to write memory management code is error prone, but it is possible to be careful (i.e., use auto pointers, stl vectors instead of arays, etc). You do need to be very good with C++, however.

      My suggestion to the author is to look at the application servers that support C++ components. I worked with a small, relatively unknown server, but even that product had a feature that kept the server up even when some C++ component (running as a forked process) crashed.

    22. Re:You're not the first one.... by asmussen · · Score: 4, Funny

      What? You need to use ones AND zeros??? Loser...

      --
      Shawn Asmussen
    23. Re:You're not the first one.... by Anonymous Coward · · Score: 1

      2. Like was said, heavily consider going to a VM langauge (Java, .NET), unless you are willing to invest a lot of extra time in testing, code review, analysis, etc.

      Java and .NET aren't going to save you from having to do any of that.
    24. Re:You're not the first one.... by Nataku564 · · Score: 2, Insightful

      Its not a tinfoil thing, its a stupid people thing.

      Microsoft doesn't want people to say "Interpreted", because that means slow. So they made up their own buzzword which means "better", or something. Its stupid, and all the MS Zealots have latched onto it. The VB.Net guy at work finally spouted it out enough times to annoy me into destroying his perceptions. Eventually it broke down into him getting frustrated and saying "Well what does interpreted really mean anyway, it could mean anything?", to which I said there was a very clear and distinct definition, and that he needs to read more books and less M$.

      Yeah, I know, hotspot compilation down to native code, Java guy rant, .NET guy rant, blah blah blah. In the end, its still interpreted - its just a very very smart optimizing interpreter.

    25. Re:You're not the first one.... by The_Wilschon · · Score: 1, Interesting

      Some literature (well, anecdote) on why you should use lisp: http://www.paulgraham.com/avg.html

      --
      SIGSEGV caught, terminating

      wait... not that kind of sig.
    26. Re:You're not the first one.... by Fulcrum+of+Evil · · Score: 1

      Or you could checkpoint your processing and run a parent process to monitor and restart as needed. Of course, nothing will save you from code bugs - best approach there is good development practices.

      --
      "We returned the General to El Salvador, or maybe Guatemala, it's difficult to tell from 10,000 feet"
    27. Re:You're not the first one.... by Hurricane78 · · Score: 1

      You make a statement but don't say why. Because i like haskell too (still a beginner in haskell), nut i also don't really understand the bad thing inside his statement...

      Is it because haskell is the only really type-safe and purely functional thing out there? (I'm not so sure that this is even true)

      Please enlighten us, oh great master lambda of curry! ;)

      --
      Any sufficiently advanced intelligence is indistinguishable from stupidity.
    28. Re:You're not the first one.... by SanityInAnarchy · · Score: 1, Interesting

      We use C# for its nice GUIs; C++ for cross-platform portability.

      *cough* *choke* WHAT?

      C++ takes a lot of platform-specific work to become portable, unless you're using portable libraries to do it for you. C#, if done well, is already portable -- and what's more, has Java's "Compile once, run anywhere", to some extent -- look at Mono.

      C++ has lots of nice GUIs, and so does C. C# has some nice GUIs, but is lacking a few major this, like OpenGL. You can write bindings for them, but in C++, nobody has to write bindings, because almost all GUIs are natively C or C++, and must have bindings written for anything else.

      And a well designed C# program is easier to write than a well designed C++ program. If your algorithm is broken, sure, nothing will work, but if it's your implementation that needs work, C# is a big help.

      Now, if only someone could tell me why C# is better/worse than Java?

      --
      Don't thank God, thank a doctor!
    29. Re:You're not the first one.... by SanityInAnarchy · · Score: 1

      Well-designed systems will be easier to develop with a garbage collector, and a traditional garbage collector can often perform better than a refcounting scheme.

      --
      Don't thank God, thank a doctor!
    30. Re:You're not the first one.... by Anonymous Coward · · Score: 0

      The worry is (and I think the GP was trying to point this out) is that the illusion of a reliable program is as troublesome as one that simply crashes. If the language is structured in such a way that crashes are difficult to produce it does not make the other code any more reliable. So in some ways programs that don't crash may give a false sense of security as under extreme time pressure it might be possible to produce code that does not crash and does not produce incorrect results given even an extensive set of test inputs but is still not correct. But then no language gives any sort of certainty that the logic is correct and that is down to code review, testing, correct design in the first place, and all the other mundane things.

      What I think is more important for a language is to make correct code easy to write. If checking for buffer overruns is too difficult then under time pressures people may cut corners when programming if they feel it is not strictly required for the application to be particularly secure. However code has a habit of being reused in situations that it wasn't designed for. But if, say, either the language or the IDE, or whatever, makes it harder to write code containing buffer overruns harder in the first place then this is good.

      To be honest, though, I think the main issue is in design of modules and their handling of what happens when inputs are outside that expected. Often specifications define what to do when inputs are those expected, or some of the unexpected cases, but not all of them. It is tedious to write code to trap all the unexpected cases and return the appropriate return values, exceptions, or whatever, so some of these can be missed out. (And this can happen as much with C# as C++). Then given incorrect behaviour with unexpected inputs incorrect results can be returned to other modules, etc., etc., and chaos can result. This is an issue of design and its impact on implementation rather than the implementation language. Few organisations go through the formal specification process and languages required to eliminate this. However given the number of vulnerabilities being found in applications connected to the internet and the increasing amount of sensitive, personal information being stored, passed around, and so on, I would hope there will be an increasing emphasis on this sort of design and implementation process. It is VERY tedious, though.

    31. Re:You're not the first one.... by renoX · · Score: 0

      He said they're using C# for GUI, are GUI in C# portable?

      In the default aka most used options, they're not..

    32. Re:You're not the first one.... by Anonymous Coward · · Score: 0

      "C++ takes a lot of platform-specific work to become portable, unless you're using portable libraries to do it for you."

      It depends what you are doing. If you are using threads, sockets, etc. then this is very true. There are some good
      portable libraries out there (e.g. ACE) although you always have to worry about support for these. This having been
      said there are quite a few out there with full source under the LGPL you can utilise (so support is slightly less
      of an issue), although how useful that is might depend on how you deploy the code.

      "C#, if done well, is already portable -- and what's more, has Java's "Compile once, run anywhere", to some extent --
      look at Mono."

      But here you are:

      1. Taking a bet on Mono continuing. (And Microsoft could kill it via patent litigation, although this isn't likely)
      2. Taking a bet on Mono being fully compatible with .NET. You have to test on all development platforms anyway,
            so you can test to see if it is compatible when you are testing your code, but you might not be sure when picking
            implementations whether the code will fail on Mono due to some unforseen incompatibility or flaw in Mono's
            reimplementation of .NET. If I was recommending starting a project I would advise against using a .NET solution
            even if the target was WIndows if it was felt that it might need to be deployed on a non-Windows system because
            of this. If I found that the requirements changed after 90% of development had already been done in .NET then
            Mono might be appropriate. The reverse goes too - I'd be wary about using Mono for a project likely to be
            non-Windows if the suggestion was to deploy a Windows version on .NET. There might be incompatibility. .NET has a lot good to be said for it, though. As does Java, as does C++. There are places for each of them. .NET is well done, but its flaw is that it is Windows-centric at the moment.

      Java does well for network code, and even for some computational code where you don't want to recompile, but the
      Java platform has a huge variety of additional libraries that it is hard going sometimes.

      C++ is great for some things too.

    33. Re:You're not the first one.... by mikaelhg · · Score: 1

      A well-designed system doesn't use a garbage collector.

      A True Scotsman doesn't use an umbrella.

      Results-oriented or reality-based people, however, might disagree...

    34. Re:You're not the first one.... by root-a-begger · · Score: 0, Troll

      Doing it all in C++ is certainly asking for trouble. I do recognize your assertion that it all must be C++, but this assertion needs to be seriously rethought. Its by far not the best choice of langugage for your stated requirements.
      The bottom line is, if you need performance and already have most of this in C/C++ libraries, then use them.
      For the overall system, UI, inter-proc communications, concurrency, etc... don't use C++.
      My plug is for you to use erlang (yes I'm serious www.erlang.org) for the entire system and make your C/C++ library calls through that. You will get great performance and not have to worry about system stability, portability and concurrency. Respost your question to the erlang questions maillist and you will get very well thought out responses.
      If you choose to do absolutely everything in C++, your just wasting time, money and the slashdot community's time as well since this type of question has well been answered in the past.
      Feel free to get in touch if you need more charitable info on why erlang is the best choice for the encompassing system archtecture.
      good luck

    35. Re:You're not the first one.... by alexmipego · · Score: 1

      Use the tools that were developed to solve that problem! Use .Net and Mono, why?

      1. Development time is much less and the code is easier to mantain
      2. Performance is excelent, very close to native code (because the code is actually compiled into native code at runtime, so you even take advantage of each processor strengs without doing separate builds with separated flags)
      3. From Linux or Windows to the other, its a very small step, if you take care your application will run on Linux, Windows, Mac, etc... even Nokia 770! with a very small, or none, effort
      4. If you need to use some C/C++ libraries, either because they aren't avaible in .Net or for performance reasons, .Net has P/Invoke, specificly developed to make that easy. You only need a 'extern' in C and a DllImport in C#
      5. Security and stability are first class citizens in .Net. It manages your memory avoiding leaks, security flaws and buffer overflows, without a single line of code! And because of the the memory manager algoritms, it is known to perform much better than the alloc and free - things like that :P - in C/C++

      And if you're thinking - hey! I don't want my users to install mono and/or .Net! - you can use Mono's tool mkbundle to create a standalone binary file. mkbundle creates you a binary file with *only* the .Net libraries code your application needs, reducing size and easing the deployment.

    36. Re:You're not the first one.... by Stocktonian · · Score: 2, Insightful

      Wow, how did this get modded insightful?
      I'm the furthest thing from a Microsoft Zealot, I don't use any MS products and don't recommend them in my consultations, but I still know that Managed != Interpreted. You've mistaken the term "Just In Time compilation" (JIT) for "Managed Code". You even have the nerve to call other people idiots! Mono has an option for performing Ahead of Time (AOT) compiliation to produce native binaries that can still be considered managed because they have been through the verification process. I think the Microsoft equivalent is called Bartok.
      May I suggest you spend a little less time reading anti-MS propaganda and either read some of these books you are so keen to suggest or spend some time actually thinking about what you say, before you say it.

      --
      XePhi Computers sell really cheap Linux CDs! http://www.xephi.co.uk
    37. Re:You're not the first one.... by Anonymous Coward · · Score: 0

      Totally-missing-the-point-and-recommending-a-diffe rent-language post, number 2,813,141,093:

      managed code is getting faster and can be pretty stable.

      If you mean .NET, forget it. Proprietary and slow.

      If you merely meant "a safer compiled language", however, then ML is ideal. It is literally as fast and efficient as C++ - not just "theoretically it might be able to optimise better at runtime", like VM-based languages, but because it's compiled to machine code just like C++, it is literally just as fast, and often faster. Some implementations, like OCaml and MLton, have even been explicitly designed to be efficient for numerical computation. But it's also a typesafe language in which a whole variety of common C++ bugs are simply impossible. (For example, there's no such thing as an access violation - nullability is expressed in the type system, so if you have a pointer that could possibly be null, the compiler won't let you use it unless you've written code to handle the case where it is null.)

      Oh, and most implementations have pretty good FFIs these days, so using C++ libraries isn't a problem.

    38. Re:You're not the first one.... by gothfox · · Score: 1

      Yeah, I know, hotspot compilation down to native code, Java guy rant, .NET guy rant, blah blah blah. In the end, its still interpreted - its just a very very smart optimizing interpreter.

      Yeah, I know, gcc, object files, native code, blah blah blah. In the end, C code is still interpreted - it's just a very very smart optimizing caching interpreter.

      What dimwit could mod this drivel insightful is beyond me.

    39. Re:You're not the first one.... by alexmipego · · Score: 1

      You're wrogn. .Net isn't interpreted. It is pre-compiled into CIL (Common Intermediate Language) and in run-time (when loading a library/class/etc...) the JIT (Just in Time Compiler) creates native code.

      1. Yes, it can lead to a slower than usual application startup. After that the application runs at native speed.
      2. Unlike native code compilers, and because it is a JIT (*Just in TIME....) is optimizes to your current processor and/or system. No need to do diferent builds to each processor and system configuration.
      3. If you think that JIT sounds bad and means slow startups you're worgn. It is pretty fast (I've experience with huge applications) and even so, it is done once then cached in the users system.
      4. Whats cached anyway? The almost native code build :) In fact, using Mono, you can get a real native code binary file, that will run on that system or another compatible (because it is optimized to your current processor and system....)

    40. Re:You're not the first one.... by chiph · · Score: 4, Insightful

      Absolutely.
      What I'm hearing is the guy's boss telling him "And it'd better not crash!"

      Typically, when absolute reliability is needed (nuclear power plants, spacecraft, pacemakers), you start subtracting libraries which aren't known to be absolutely reliable, yet in this case they're adding them. In addition, he's wanting it to run on multiple platforms, which radically increases your testing workload.

      On top of that, he admits he's got no experience in the techniques needed to produce reliable software. Probably has a short deadline, too.

      My crystal ball says he's doomed to failure.

      Chip H.

    41. Re:You're not the first one.... by JoeMerchant · · Score: 1
      Ultra stable - core libraries - does not compute......

      Seriously, if you're looking to the core libraries to do any heavy lifting, you'd better exhaustively test them for every conceivable and inconceivable scenario in which you will be using them... they're not your code, and therefore will not be predictable in their behavior.

    42. Re:You're not the first one.... by SavvyPlayer · · Score: 1
      .NET is well done, but its flaw is that it is Windows-centric at the moment.
      And its threading implementation is at best half-baked. .Net 1.1 is lacking certain fundamental threading features necessary for any application of the type the OP is designing:
      • No semaphores
      • No propagation of unhandled exceptions
      • The thread manager is reimplemented entirely within the CLR (no efficiencies gained or functionality inherited from the OS thread-manager)
      • Thread creation is very expensive, and going beyond the default thread pool limit of 25 threads is highly impractical for this reason.
    43. Re:You're not the first one.... by Anonymous Coward · · Score: 3, Interesting

      Purely functional languages have two big advantages applicable in this case:

      * No (or very, very limited) side-effects. In other words the result of a function is not dependent on the current program state. Once it is exhaustively verified in testing, that function will forever more return the correct results because the run-time state won't affect it.

      * The language itself can often be treated as a specification of correctness, and even formally proved through static analysis. As a trivial example if you write an implementation of factorial in Haskell, it strongly resembles the mathematical definition of factorial -- the code is more of a description of what the correct result is, rather than a set of low-level steps for carrying out the computation as in C.

      Haskell is nice, however I think the original questioner is better off with something like Erlang, which was designed for just this kind of situation. If it's good enough for telephone switches...

    44. Re:You're not the first one.... by Anonymous Coward · · Score: 0

      I'm sorry, but this is just not true for C++. Using character arrays is just done by the hackers and truely stupid. C++ has the string class to take care of this, which does all the allocation etc. You must be thinking of C when you are referring to having design problems. I find most people who think C# is easier, never actually did any real C++ but just read some C examples from John Doe on the web and assume C++ is about memcopying stuff.

      Bottom line is:
      - Stay clear of pointers by using more references
      - Prefer copying data to optimalization by anything else, optimalization should come last if, and only if, needed.
      - Never do pointer arithmatic, you arn't smart enough believe me
      - Understand an use the STL classes, they are there for memory management and are very usefull.
      - Never cast anything, you shouldn't have to. And if you do have to, encapsulate en isolate the cast with asserts.
      - Use BOOST smart pointers and garbage collection if needed.

      If you don't understand one of the above, use a more protective and restricting language like Java or C#. If you do understand these points, then your design won't be crippled in any way suggested in these posts.

    45. Re:You're not the first one.... by j.leidner · · Score: 2, Insightful

      I agree. Haskell is a bad choice _at_present_ at least for the following reasons: (a) hard to find qualified staff to maintain the code, (b) language not standardized and still in flux.

      This is not a comment against Haskell, but against suggesting it as appropriate means, given the poster's situation.

    46. Re:You're not the first one.... by The_Wilschon · · Score: 4, Interesting

      More: http://www.cs.indiana.edu/~jsobel/c455-c511.update d.txt about a guy who wrote the "Fast Multiplication" algorithm very simply in scheme, and then transformed it (using correctness preserving transformations, which are much much easier to do in "Haskell or one of the other functional languages" than in C/C++ and friends) into scheme code that was as optimized as he could come up with, and which furthermore had a pretty much 1-1 correspondence with C statements. He then rewrote it in C (including perfect "goto"s!), and beat all but one person in his class on the speed of the algorithm. Furthermore, he spent significantly less time working on (read debugging) his code than anyone else in the class.

      --
      SIGSEGV caught, terminating

      wait... not that kind of sig.
    47. Re:You're not the first one.... by msobkow · · Score: 1

      What, praytell, is the difference between a functional language like Haskell and a well-designed C++ template library? A few pure abstract classes acting as interface specifications, and you plug-and-play the implementations based on the data being transformed -- which is all that a functional language does behind the syntax and performance tweaks.

      Make use of a factory interface for instantiating objects so the business programmers don't need to deal with the nitty-gritty of C++ syntax (which can be a tad typo-prone.)

      Follow the ownership of the objects throughout your implementation. At any given time, one object owns another, with the owner responsible for releasing it's children before itself. Java J2EE still requires the concept of an explicit release/free to coordinate resources; only J2SE lets you more or less ignore deallocation.

      Alternatively, impose a use counter or make use of one of the OSS instance management libraries out there.

      As has been mentioned previously, test often, and make sure to do regression runs when making changes to the architectural approach.

      Make heavy use of DEBUG-flagged assertions to state your assumptions about the data when code is executing. If those assertions go off in testing, either you're making bad assumptions or there is a problem with the data source. You should be able to disable the DEBUG code in production -- no DEBUG-flagged code should have side-effects.

      Always validate remote API arguments. You mentioned a distributed application -- assume the peer is going to send you garbage, and deal with it.

      Don't forget to unplug network cables randomly during load testing. It will happen in the real world. How does the cluster deal with that?

      And the list goes on...

      --
      I do not fail; I succeed at finding out what does not work.
    48. Re:You're not the first one.... by Poltras · · Score: 1
      You might want to take a look at SML, a precursor to Haskell in functionnal programming languages, and it is type-safe and purely functionnal (even more than haskell I think, but I've only seen a couple of examples of haskell 2-3 years ago).

      And I disagree with you, the statement did NOT make sense. Even though there's a lot of packages out there for functionnal languages (FL), which could cover all functionnalities for such a project, the article mentions speed. Unfortunately, even compiled FL cannot compete with structural ones, because FL are from a different class of languages by definition (see lambda calculus versus turing machines).

    49. Re:You're not the first one.... by laffer1 · · Score: 1

      Yes and as someone else pointed out the person could use .NET 2 above that has many of these features, the mono project DOES NOT support .NET 2 code at this time. The parent is right.

      In fact, I'd say scrap the .NET idea all together since Linux is a requirement. Mono is not ready for production use because its not compatible yet. Someday maybe it will work on Linux and provide 2 operating systems for which .NET can run. I don't believe that solaris or mac os x ports will ever work the same as the Linux port. The lack of interest in fixing BSD bugs in the Mono project is proof they don't care about other platforms. (and it is Novell and Western Michigan University grads we are talking about)

      If the requirements for his proposal only required windows, .NET 2 would be a great solution. I agree with everyone else that a higher level language is the way to go. If the person insists on C++ on windows, don't use the MS compiler if you want some portability. If money is no object, maybe licensing Qt for windows and Linux is a good idea. Gtk might work as well.

    50. Re:You're not the first one.... by msobkow · · Score: 1

      In other words crafting stable C++ is as much about process, code samples, and enforcing standards as it is about selecting the right tools.

      --
      I do not fail; I succeed at finding out what does not work.
    51. Re:You're not the first one.... by Tenareth · · Score: 1

      I love this, you people make it sound like there was no code before Java. You realize that most imbedded code is Assembler or C, right? You realize that before "managed" code that bad programmers could use to not suck so much, there was plenty of good stable programs.

      I know Microsoft has worked hard to convince everyone that C/C++ suck, but just because the largest software company in the world can't get code to work doesn't mean it is the fault of the language. C++ can be extremely stable if you spend a little bit of time making sure you don't assume anything.

      Unstable code has nothing to do with the language, and everything to do with the programmers.

      --
      This sig is the express property of someone.
    52. Re:You're not the first one.... by Nataku564 · · Score: 1

      If I kill the java process, does my program still run?

      Good, now that we have that bit of understanding down, would you mind telling me where the gcc process is while I am running C++ programs?

      Yes, the hotspot thing does perform compilation down to native code, and yes that makes it darn fast, but its still entirely reliant on the java process to figure out what to compile, when to compile, etc. For all you know, the thing could decide to compile none of your program down to native.

      If your code runs natively on the hardware by itself (that part is important) then you have a compiled program. If it relies on some other process to read it in and figure stuff out, its interpreted. Compiler books will agree with me.

    53. Re:You're not the first one.... by Nataku564 · · Score: 1, Interesting

      I figured people would get all wound up when anyone says anything contrary to their mantra.

      Do some googling, and see that Microsoft says that "managed code" is something that is executed by the .NET framework. Therefore, if you compile it down, its no longer "managed code". My issue isn't with non-compiled languages - heck, my primary language is Perl of all things - my issue is with Microsoft coming up with a new term for an old idea so they can brainwash people into forgetting what it means.

    54. Re:You're not the first one.... by sketerpot · · Score: 1

      I agree that there aren't a whole lot of people out there who can maintain Haskell code, but your comment about the lack of standardization is misleading. There is a stable Haskell 98 standard which specifies the core of the language; the problem is that Haskell 98 is conservative, and some very useful extensions have come into common use. If you just use the GHC compiler and forget that nhc and hugs exist, lack of standardization shouldn't be a big problem.

    55. Re:You're not the first one.... by Nataku564 · · Score: 1

      My issue is not with how fast or efficient languages are. My issue is with Microsoft defining a new term so they can avoid an old one that means the same thing. If your program is a binary file, and can run natively on the hardware, you are compiled. If your program relies on some other program to interpret it and run it, then it is interpreted. The interpreter may decide to spit out binary and run that, but the interpreter is still there, and if you kill it, your program no workie anymore. It is this reliance that defines interpreted programs.

      I like interpreted languages, and they dont really deserve some of the reputation they get from the word. Heck, I use Perl of all things, and I love it. But I will be the first to call the kettle black.

    56. Re:You're not the first one.... by ultranova · · Score: 1

      I love this, you people make it sound like there was no code before Java.

      Of course there was. So why was Java born ? I'd imagine it was to solve some problem...

      You realize that most imbedded code is Assembler or C, right?

      And you realize that code running in total control of a single-purpose embedded device and code running in a multitasking computer (or several computers, if you're talking about distributed applications) have very little to do with each other, right ?

      You realize that before "managed" code that bad programmers could use to not suck so much, there was plenty of good stable programs.

      And there were plenty of horrible, unstable ones too - and there still is.

      Of course it is possible to make a stable program with a nonmanaged language, it is simply a lot harder.

      I know Microsoft has worked hard to convince everyone that C/C++ suck, but just because the largest software company in the world can't get code to work doesn't mean it is the fault of the language. C++ can be extremely stable if you spend a little bit of time making sure you don't assume anything.

      Perhaps you might explain how one can code without assuming anything, since that would logically mean that you can't assume that the basic language constructs do what you think they'll do either - which, as it happens, is perfectly justified paranoia in C++, thanks to overloading ?

      Unstable code has nothing to do with the language, and everything to do with the programmers.

      True. Which is why it makes sense to make the computer handle error-prone low-level details like memory management :).

      --

      Forget magic. Any technology distinguishable from divine power is insufficiently advanced.

    57. Re:You're not the first one.... by ultranova · · Score: 2, Informative

      If I kill the java process, does my program still run?

      Of course it doesn't - you just killed it.

      Good, now that we have that bit of understanding down, would you mind telling me where the gcc process is while I am running C++ programs?

      C++ runtime libraries are loaded into the programs memory space. Just like the Java runtime is in the memory space of whatever Java program you are running. The difference is that the operating system has a specific loader for the kind of files (ELF in Linux) C++ compiler produces, and labels them according to this file in the list of running programs instead of labeling them all as ld.so processes; on the other hand, Java runtime contains its own code for loading Java programs, so the system will label them all as Java processes.

      Did this have any point ?

      Yes, the hotspot thing does perform compilation down to native code, and yes that makes it darn fast, but its still entirely reliant on the java process to figure out what to compile, when to compile, etc. For all you know, the thing could decide to compile none of your program down to native.

      And for all you know, gcc could just cat your C++ source files together and add a runtime interpreter to them. If that runtime interpreter was "darn fast", would you know or care ?

      I'm trying to understand your point, I really am, but it seems to be some weird idea of interpreted language being bad even if it is as fast as a precompiled one, and that just doesn't make sense to me.

      Also, did you mean "Java runtime" instead of "Java process" - since the JVM and the program being run form a single process, just like a C++ program and its runtime libraries, so this really doesn't make sense otherwise ?

      If your code runs natively on the hardware by itself (that part is important) then you have a compiled program. If it relies on some other process to read it in and figure stuff out, its interpreted. Compiler books will agree with me.

      C is interpreted, then. On Linux, a C program depends on ld.so to bring all the neccessary C libraries to the process's memory space and link it just prior to execution (or during execution, if you use dynamic lib loading). And, of course, it is the kernel process that reads it to memory in the first place.

      More generally, each and every program depends on some other process to read it in and "figure stuff out", unless you want to suggest that the code will magically jump from the disk to the main memory ? BIOS is propably the only exception to this rule, since it resides in ROM and is in computers main memory at boot. Every other program, including operating system, is loaded by some other program and therefore interpreted by your standards. And of course a modern process will also change machine code execution order to get more execution speed - a clear example of compilation :).

      The real question is: does it matter ? Why on Earth would I care if my code satisfies some completely arbitrary requirement of being "non-interpreted", if the interpreter is so smart that I can't measure a speed difference ?

      --

      Forget magic. Any technology distinguishable from divine power is insufficiently advanced.

    58. Re:You're not the first one.... by Anonymous Coward · · Score: 0

      Um, he said something about runtime performance.

    59. Re:You're not the first one.... by synthespian · · Score: 4, Funny

      What, praytell, is the difference between a functional language like Haskell and a well-designed C++ template library?

      Referential transparency.
      That comp.lang.functional thread is interesting because there are guys from Ericsson elaborating on some real-world aspects of referential transparency. As you know, Ericsson uses the funtional programming language Erlang for their switches. See more in: Welcome to a Smarter Way of Programming. Of course, you can't take their use of Erlang seriously, because they're from Sweden, and Sweden, being a fucked-up third-world country with no tech at all, is not an example for America. The mighty AT&T pushed C++, and now the world is better, safer place, where software errors are a thing of the past.

      --
      Main difference between the BSD license and the GPL license: one is from California and the other is from Massachusetts
    60. Re:You're not the first one.... by glitch23 · · Score: 0

      C#, if done well, is already portable -- and what's more, has Java's "Compile once, run anywhere", to some extent -- look at Mono.

      Mono covers the Linux platform. Is there anything for HP-UX, AIX, or even SGI that makes C# run on those platforms or by portable do you mean Windows, Windows, Windows, and Linux?

      --
      this nation, under God, shall have a new birth of freedom. -- Lincoln, Gettysburg Address
    61. Re:You're not the first one.... by pthisis · · Score: 1

      OCaml and Dylan (the latter with optional strong-typing enabled) are widely-available real-world type-safe functional languages, and as another response noted SML is another (really, SML and Ocaml are both variants of ML).

      Ocaml is high-performance, type-safe, functional, and freely available under an open-source license (I think it's QPL 1.0 for the compiler, GPL 2.0 for the libs)

      --
      rage, rage against the dying of the light
    62. Re:You're not the first one.... by Stocktonian · · Score: 2, Informative
      So where does it say that managed code can't be native? It is still managed as long as it retains the metadata describing it. I can't stand Microsoft as much as the next Slashdotter but they've not renamed interpreted code. Managed means something very different. The .Net framework isn't a compiler or interpreter, it's a fully fledged virtual machine. The usual way of running that machine is alongside the code you want to execute, doing JIT compilation. An alternative is to create a managed executable running under the .Net framework, with access to libraries and CLR features, but using native code.

      By the way I couldn't care less what you say about "the mantra", I just don't like it when false information gets spread. So until you can find proof that "managed code" running under the CLR requires that it be interpreted, I'm going to stick with the impression you're wrong.

      Sources: The Common Language Infrastructure Annotated Standard [1st edition] pg 8.
      How and when the CIL is compiled to machine code are not specified as part of the standard, and those determinations rest with the implemention of the VES. The most frequently used model is just-in-time (JIT) compilers ... Install-time compilers are another option...
      Figure 1-4 (Execution Model) on the following page clearly shows "unmanaged native code" and "managed native code" existing along side each other. Since this book is basically an expanded version of the ECMA CLR specification the quote and figure are probably available online for you to check but the page numbers are probably different.

      Please cite your sources that show managed code==interpreted and hence satisfy your premise before drawing the conclusion that MS have redefined terminology.
      --
      XePhi Computers sell really cheap Linux CDs! http://www.xephi.co.uk
    63. Re:You're not the first one.... by spectre_240sx · · Score: 1

      Next time your found, with your chin on the ground
      There a lot to be learned, so look around

      Just what makes that little old ant
      Think he'll move that rubber tree plant
      Anyone knows an ant, can't
      Move a rubber tree plant

      But he's got high hopes, he's got high hopes
      He's got high apple pie, in the sky hopes

      So any time your gettin' low
      'stead of lettin' go
      Just remember that ant
      Oops there goes another rubber tree plant

      When troubles call, and your back's to the wall
      There a lot to be learned, that wall could fall

      Once there was a silly old ram
      Thought he'd punch a hole in a dam
      No one could make that ram, scram
      He kept buttin' that dam

      'cause he had high hopes, he had high hopes
      He had high apple pie, in the sky hopes

      So any time your feelin' bad
      'stead of feelin' sad
      Just remember that ram
      Oops there goes a billion kilowatt dam

      All problems just a toy balloon
      They'll be bursted soon
      They're just bound to go pop
      Oops there goes another problem kerplop

      --Writer(s): cahn/van heusen

    64. Re:You're not the first one.... by Anonymous Coward · · Score: 1, Insightful

      You are confusing interpreter with virtual machine. You can have a compiled binary for a virtual machine that is not a native binary. You can also have an interpreter for a virtual machine (e.g. the original JVM), or you can have a JIT compiler for a virtual machine (e.g. the CLR). The former executes the virtual machine binary, the latter creates a native executable from the VM binary.

      Microsoft uses the term "managed code" to mean a CLR binary that has a certain set of guaranteed properties: verifiable type safety which means no illegal memory accesses, and enables strict garbage collection, and fine-grained security control. You can write unmanaged code for the CLR (i.e. create VM binaries, that are not type safe) that still follow the same execution path (compiled to a CLR binary and then JIT compiled to be executed).

    65. Re:You're not the first one.... by Anonymous Coward · · Score: 0

      You know, I was with you up until the end there. Why did you feel the need to turn this into a US vs EU argument? While the OP was written from a perspective of ignorance no one said a damn thing about Sweden.

      So sorry that a US company held your pet language down. So sorry how us stupid USians keep beating your superior companies with our inferior products. So sorry.

    66. Re:You're not the first one.... by Soybean47 · · Score: 0, Flamebait

      So, just to clarify... what you're decribing is a fantastic way to be second best? ;)

    67. Re:You're not the first one.... by brpr · · Score: 1

      SML isn't purely functional, it has side effects.

      --
      Freedom is not increased by mere diminuation of government. Anarchy is freedom for the strong and slavery for the weak.
    68. Re:You're not the first one.... by Hurricane78 · · Score: 1

      As far as i know ocaml allows side-effects, which is pretty much the root of all evil, right?
      So i would not recommend it as a secure language.

      Additionally it does no lazy evaluation and allows imperative loops.

      Maybe side-effects and imperativity make it fast. But that's a pretty hight price if you go for stability at any time...

      --
      Any sufficiently advanced intelligence is indistinguishable from stupidity.
    69. Re:You're not the first one.... by brpr · · Score: 1

      I think there was a touch of irony in the grandparent which you missed (typical American...)

      --
      Freedom is not increased by mere diminuation of government. Anarchy is freedom for the strong and slavery for the weak.
    70. Re:You're not the first one.... by Jezza · · Score: 1

      Objective C++, create wrappers for the C++ classes. This isn't a silver bullet, but the result is much easier than C++. C++ is a pig of a language, limiting programmers to Objective C makes code much easier to read (and single superclasses are easier).

    71. Re:You're not the first one.... by MagicMike · · Score: 1

      As an American, I have to say, my compatriots frequently and quite unintentionally provide some of the best people-watching by completely missing irony. Always good for a quick chuckle.

      As my high school chemstry teacher said, it takes alkynes.

    72. Re:You're not the first one.... by Hurricane78 · · Score: 1

      haskell - as i said - seems to have the main target on functional programming. I don't think something out there can beat that strictness. For many jobs it even feels to strict. (or using its non-functionals part (monads) does feel too dirty...;)

      Your second paragraph makes not much sense because like the great-grandparent post you place statements on the room, but you don't add any arguments why you think it's that way. That way you can't convince anyone. Such statements only work for poeple who let you coax themselves. ;)
      I don't know if you intentionally left the arguments away because you knew it was not that right, because you thought it's a paradigm, or because of something else, but when you want to be taken seriously: add arguments (preferably based on paradigms or previous statements that where based on paradigms).

      To come back to your statements:

      > Unfortunately, even compiled FL cannot compete with structural ones, because FL are from a different class of languages by definition (see lambda calculus versus turing machines).

      What i'm missing here is the reason, why being able to compete implies that the languages have to be from the same class.
      (Argument [real world example]:) I can easily compare them. I take a set of the best implementation of often used problems on those languages, run them N times and measure time and space usage. Then i can take the one with the lowest numbers in the area that is most important to me.

      --
      Any sufficiently advanced intelligence is indistinguishable from stupidity.
    73. Re:You're not the first one.... by Anonymous Coward · · Score: 0

      Java, Java, Java... Everything you need can be accomplsihed through Java. See recent /. story about photo fraud software originally done in metlab now being developed for production use in Java. Plus, "right out of the box" you get linux, xp and mac all in one shot (despite what the critics will have believe). Manage code is obviously a good idea for this, but if one is considering C++, then one is clearly able to develop in Java - and as a bonus, most of the "crash" causing bugs are avoided from the get go.

    74. Re:You're not the first one.... by aspx · · Score: 1

      Managed code will do nothing to prevent a deadlock, and it will not deal with incomplete error handling.

      I think the OP is on the right track.  It is better to focus on recovery, rather than trying to write code that cannot fail.  Even still, there are situations where recovery is not possible.  E.g., your application requires a database, but the database does not respond.  Plan for and test all the recovery scenarios that you want to be able to handle.  Input that is known to cause a crash should be logged (and not reprocessed!) along with system state for quality improvement.  Some input will cause a failure every time, while in other cases the system must be in a certain state before the failure will occur.  The Command Pattern will be useful for this.

      For an extra measure of system reliability, use/recommend fault tolerant hardware such as RAID 5 arrays, ECC memory, etc.

    75. Re:You're not the first one.... by swmccracken · · Score: 1

      But what about non-CLS* compliant code running in the CLR?

      As far as I know, it's possible to have C++ compiled with VS.Net into MSIL and is thus interpreted/jit'd but is still unmanaged because it is using C++ style classes, memory managment and all that.

      In fact, I once took the nethack source code, compiled it for Windows using VS.Net 2003 targeting the CLR "processor" instead of x86. It was unmanaged - classic C and C++ memory managment and calls to native library - but was still MSIL, at least as far as I could tell.

      *CLS == Commmon Language Specification. MS speak for java-style GC'able type-safe blah blah languages.

    76. Re:You're not the first one.... by oever · · Score: 1

      So is CLR like a cross between the Java Sandbox and chroot? If so and it can run native code, how does it protect against buffer overruns? In other words, what is it that's being managed (apart from the consumer ;-) ?

      --
      DNA is the ultimate spaghetti code.
    77. Re:You're not the first one.... by Peaker · · Score: 1

      When gracefully handling fatal and/or process-management signals becomes as easy as catching exceptions, unix will freeze over.

    78. Re:You're not the first one.... by HermanAB · · Score: 1

      No, it is not that simple. See this: http://www.hpl.hp.com/personal/Hans_Boehm/gc/issue s.html

      --
      Oh well, what the hell...
    79. Re:You're not the first one.... by ServereNerd · · Score: 1

      Since you're running multiple nodes, you should try to decrease the inter-node dependencies as much as possible. You don't want an error in one cascading to the others.

      You will also want to error check as much as possible. Don't let functions/methods operate on corrupt arguments! If a function gets some bad values, don't accept it and try to get it to error gracefully. The more assumptions you make about the input to a function, the more potential problems you can have. For instance, always check the bounds of any index to arrays or STL vectors.

      You will also want to be able to detect errors in other nodes. You might be able to make the nodes "back up" their progress in case one fails, so it doesn't have to start from the beginning.

    80. Re:You're not the first one.... by menkhaura · · Score: 1

      Lesseee...


      double factorial(double n)
      {
              if(n==0)
                    return 1;
              else
                    return n * factorial (n-1);
      }


      Except for the return statement and the braces (i.e., slight differences in notation), this looks pretty much like the mathematical definition of factorial...

      --
      Stupidity is an equal opportunity striker.
      Fellow slashdotter Bill Dog
    81. Re:You're not the first one.... by aminorex · · Score: 1

      While I agree with you in the main, SIGSEGV handlers are sheer hubris. There's good reason to distrust any code running after a segfault. It's much better to deal with such conditions from the safety of another address space.

      --
      -I like my women like I like my tea: green-
    82. Re:You're not the first one.... by KermodeBear · · Score: 1

      Oh so true.

      I work as a web application developer and my manager wants to move everything over from PHP to C#. Why? "Well," he tells us, "it's easier to find good programmers and writing good code is easier in C# than in PHP. You'll have less bugs!"

      This is coming from the guy who wraps all his functions in a giant try/catch block so that he can return false if something broke and true if everything executed correctly. But he is an MSCD so he MUST be a good programmer! Right?

      The truth of the matter is that it is possible to write good code in just about any language (except, perhaps, BrainFuck) as long as you have a good, solid design before you start writing code.

      --
      Love sees no species.
    83. Re:You're not the first one.... by Stocktonian · · Score: 1

      It's probably easier to think of the CLR (.NET is Microsoft's brand name for the same thing) as helper libraries. These libraries collaborate with Managed Code, which is just a special file format. The libraries (and helper apps I suppose) don't run the app in a secure environment, like chroot, but rather perform tests to ensure it won't do anything bad in the normal environment, like access null pointers or manipulate buffers to get to code that should be protected. You can either do these tests at execution time and JIT compile the code, or you can run the verification tests when you install the app in a particular machine. Making it native code before execution just like a traditional compile cycle. I guess you could verify the code before installation but it would only work if you knew exactly what systems you were writing for.

      I hope that clears things up for you.

      --
      XePhi Computers sell really cheap Linux CDs! http://www.xephi.co.uk
    84. Re:You're not the first one.... by mattpalmer1086 · · Score: 1

      This is so clearly not true. It is to do with the programmers, but it's also to do with the tools. You *can* create object oriented style code in assembler, but it's so much easier if the compiler does this for you. It allows the programmer to exist at a higher level of abstraction with the messy details taken care of, and safe structures provided to use.

    85. Re:You're not the first one.... by SphericalCrusher · · Score: 1

      Agreed. Good thing this was the first comment too. Going C++ for Linux only isn't a good bet right now. Good luck on the project.

      --
      "Instant gratification takes too long." - Carrie Fisher
    86. Re:You're not the first one.... by msobkow · · Score: 1

      No irony -- functional languages have baffled me for a long time because they seem to be syntactic sugar for template/interface programming.

      --
      I do not fail; I succeed at finding out what does not work.
    87. Re:You're not the first one.... by brpr · · Score: 1

      How so? They're based on the mathematical concept of a function. It so happens that you can hack together this abstractiion using templates and interfaces in C++ or whatever (though you can't really have proper closures, and the syntax is ghastly). How would you write a template/interface-based version of the following?

      reverseList = foldl (flip cons) []

      And why on Earth would you want to?

      --
      Freedom is not increased by mere diminuation of government. Anarchy is freedom for the strong and slavery for the weak.
    88. Re:You're not the first one.... by Decaff · · Score: 1

      Some literature (well, anecdote) on why you should use lisp: http://www.paulgraham.com/avg.html

      Indeed, it is just an anecdote. And as it is just one anecdote and it is the single example brought up again and again, I would not take it as generally useful.

    89. Re:You're not the first one.... by tjrehac · · Score: 1
      With all the comments almost wonder if this is a troll...but here goes...

      Stable (or ultra-stable) software is a combination of many things. This includes at least; requirements gathering, architecture, design, coding, QA, configuration and realease management, project management, training of developers/qa/project managers/business analysts i.e. the software development/engineering process.

      Far down the list, in my opinion, is choice of language. Not that languages don't have relative strengths and weaknesses, but to think that choice of language will be the first, second or third determining factor in software stability is like wearing a seatbelt but driving blindfolded while intoxicated 155 mph in a yugo in a blinding snowstorm...you can gain some incremental survivability...but probably will add a few painful milliseconds to your life expectancy.

      Assuming you have a full grasp of the requirements, including the beginnings of your test plans, it sounds like architecture is a good place to begin.

      The fact that you are thinking about architecture concepts early is a good sign, and a modular approach is a good start. I would say the CORBA, SOAP or just plan XML messaging probably is a reasonable place to begin your inter-module communications thoughts. Make sure that you spend some time thinking about testability in your architecture - i.e. how can I test each module on a stand alone basis. There are some hardware architecture things you can add later (deploying software layers onto separate machines, adding redundancy etc.).

      Once you have solid beginning software architecture, intense OOAD is in order. Mistakes here have huge downstream affects, some almost unrecoverable without throwing away huge chunks of code - so measure twice cut once so to speak. Not sure if there is a DB in the picture - but some thought about data elements and relationships is pretty important here as well...Design in testability...

      Code (including adding testability)...

      QA

      Iterate

    90. Re:You're not the first one.... by humblecoder · · Score: 1

      Based on the original posters description, this seems less like a LANGUAGE question, and more like a DESIGN question. I see people saying, "do it in X", where X is the language flavor of the month. The problem is that no matter what language you use, if your design isn't "fault tolerant", your application won't be fault tolerant.

      I have done some work in .Net programming, and while there are certain constructs that do help, you have to design your application to use these constructs, and even then, it is no guarantee of stability.

      Here are a couple of general pieces of advice:

      1. You had a good idea as far as isolating components into separate processes, and having a master application with detects failure and restarts applications. Of course, if the master application fails, or if one of your processes crashes the whole machine, you are dead in the water.

      2. If you want to go further, you can isolate modules across several machines, with redundancy. If a machine goes down or gets disconnected from the network, you can have a fallover strategy that tries to use another machine.

      3. If your calculation is something that can parallelized, you can have an app farm that does the calculation in a distributed fashion. If any one of the nodes fails, you can redo that node's calculation on another machine.

      4. Remember all of the standard coding fundamentals that you learned in your software engineering class (high cohesion, loose coupling, only optimize code as necessary, and test the heck out of the thing).

      5. Remember that fault tolerance comes at a cost. There will always be a single point of failure, whether it be the process, the machine, the power grid, etc. Decide what level of fault tolerance you can afford, and what level you can live with, and go from there.

      I work for a company that has some critical machines that need near 100% uptime. In order to achieve that, the company has spent millions (if not billions) of dollars to build in as much fault tolerance as possible. Redundant data centers in different parts of the country, each with its own generators, water supply, multiple dedicated network connections, etc, etc, etc. I doubt that you need that level of redundancy. However, when you say that you need your application to be fault tolerant, keep in mind that fault tolerance isn't a yes or no checkbox - it is a scale. You need to decide how much fault tolerance you need, and design from there.

    91. Re:You're not the first one.... by Anonymous Coward · · Score: 0

      When writing unmanaged code, you build your architecture around the memory managment requirements first - knowing the lifespan of every object for example. What you want it to achieve becomes the second design consideration.

      With managed code your architectural design can focus exclusively on solving the problem - I say "can" because you might well stick to your C programming patterns and miss the benifit.

      Removing a whole class of human error from the project is icing.

    92. Re:You're not the first one.... by budgenator · · Score: 1

      well most PHP is a web app, and web app tend toward feature creap more than other apps so usualy PHP tends to either be poorly designed or headed that way.

      --
      Apocalypse Cancelled, Sorry, No Ticket Refunds
  2. Get another programmer by Anonymous Coward · · Score: 0

    Write with them.

    1. Re:Get another programmer by Philip+K+Dickhead · · Score: 5, Funny

      Make sure his name is something like "Bjarne" or "Knuth".

      --
      "Speaking the Truth in times of universal deceit is a revolutionary act." -- George Orwell
    2. Re:Get another programmer by Shrubber · · Score: 1

      If they're not available, getting another programmer who doesn't have to ask the slashdot crowd how to develop stable software should be the first step. Oh yeah, there's a stable group if I ever saw one.

  3. inline code by jrockway · · Score: 3, Informative

    > Sadly, the programming language cannot be changed due to reasons of efficiency and availability of core libraries.

    You can easily embed C/C++ in other languages. Take a look at Inline::CPP, for example. With code like:


          use Inline CPP;

          print "9 + 16 = ", add(9, 16), "\n";
          print "9 - 16 = ", subtract(9, 16), "\n";

          __END__
          __CPP__

          int add(int x, int y) {
                return x + y;
          }

          int subtract(int x, int y) {
                return x - y;
          }


    you can put the parts that need to be fast in C++, and the parts that need to be easy in Perl. (If you do the GUI in perl, you won't have to worry about portability or memory allocation. And the app will be fast, because the computation logic is written in C++.)

    > The application can be naturally divided into several modules, such as GUI, core data structures, a persistent object storage mechanism, a distributed communication module and several core algorithms.

    Yup. There's no need for the GUI to know how to do computations, remember. The more separate components you have, the more reliable your application (can) be. Make sure you have good specs for communication between components. Ideally, someone will be able to write one component without having the other one to "test" with. For testing, write unit tests that emulate the specs... and make sure your tests are correct!

    --
    My other car is first.
    1. Re:inline code by stoicio · · Score: 1

      "you can put the parts that need to be fast in C++, and the parts that need to be easy in Perl" Yeah, use two languages instead of one. That will make it simple and stable...*not*! Keep it coded silly, simple intead. That will lead you to stability.

    2. Re:inline code by Anonymous Coward · · Score: 0

      Don't forget it's perl though! The language that's known for its robustness, maintainability, and has been proven to write mission critical software for YEARS. Wait... what was I talking about?

    3. Re:inline code by Chandon+Seldon · · Score: 1

      The different languages have different properties. You should use the right tool for the right job, and there's more than one job in a non-trivial computer program.

      --
      -- The act of censorship is always worse than whatever is being censored. Always.
    4. Re:inline code by Prof.Phreak · · Score: 1

      That is possibly the best advice anyone can give!

      Use an easy language (like Perl) for most of the app, and write C code (either inline, or as separate programs that pipe data to/from Perl code) for things that need raw speed.

      We do this at work; processing ~20gigs of data per day without any issues.

      I've also noticed that `raw speed' doesn't really matter much in many cases---especially when you can just throw hardware at things (some of our `data processing' tasks used to run for hours... we just got a dedicated 8 processor box with 32gigs of ram, and... well... all of a sudden the job is down to 20 minutes---maxing out all CPUs, but still good).

      Probably way cheaper than rewriting the thing in C++ (not to mention saved debugging time!).

      There are cases when you -do- need pure C/C++... most data processing tasks aren't it though. Maybe games. In general, only 5% of the code needs to be "fast" (well, at least as fast as one can make it in C anyway). For the other 95% of the code, speed doesn't really matter.

      --

      "If anything can go wrong, it will." - Murphy

    5. Re:inline code by countach · · Score: 4, Insightful

      Perl? Fuck. He wants a stable app with good code. Sheesh.

    6. Re:inline code by Anonymous Coward · · Score: 0
      > you can put the parts that need to be fast in C++, and the parts that need to be easy in Perl.

      try to keep your design as simple as possibile.

      you can easily remove hundreds of lines of (possibly faulty) GUI code using C++ for the core and HTML (that's less likely to segfault!) for the GUI .

      then use KLone or a similar framework to make it a real application.

    7. Re:inline code by jadavis · · Score: 2, Interesting

      Once I did a hybrid python/C project because C by itself was impossible for me to maintain in the given time constraints.

      It worked amazingly well. There's a little bit of interfacing work that needs to be done, but I found that, in that project at least, the C code didn't need to be modified very often.

      It very often DOES simplify to use two programming languages.

      --
      Social scientists are inspired by theories; scientists are humbled by facts.
    8. Re:inline code by Jackmn · · Score: 1

      Both of which well-written Perl is fine for.

    9. Re:inline code by peterpi · · Score: 1

      You do need to worry about memory leaks in perl, as it uses refcounting instead of garbage collection.

      It's trivial to implement a memory leak in perl. Here's one in 5 nicely formed innocent looking lines.

      while (1)
      {
          my $hashref = {};
          $hashref->{self} = $hashref;
      }

    10. Re:inline code by gothfox · · Score: 1

      Sorry to burst your little groupthink bubble there, but is as possible to write big, well-coded and very readable applications in Perl as it is in any other serious language. If you are unable to code well in some $LANGUAGE, it is your incompetence that is the problem, not $LANGUAGE itself.

    11. Re:inline code by jrockway · · Score: 1

      And when was the last time you actually wrote a construct like that?

      The point is, it's easy to screw your self over in any language. If you're a bad programmer, you're going to be bad in any language. If you're a good programmer, you'll manage with any language. The fact that there's lots of bad perl scripts out there just means that there are lot of bad perl programmers -- not that perl itself is bad.

      Anyway, if you are going to do a big project in Perl, definitely read Perl Best Practices.

      --
      My other car is first.
    12. Re:inline code by jrockway · · Score: 1

      > Perl? Fuck. He wants a stable app with good code. Sheesh.

      Just because you can't read or write Perl proficiently doesn't mean that's a problem with Perl. If you're going to do a big perl project, check out Perl Best Practices first. It'll help you set a consistent, reliable, and maintainable coding style.

      Personally, I've coded a big perl app this way, and it still makes perfect sense to me (and the other hackers) 6 months later. (As opposed to a Java program that I could no longer understand after a 36-hour coding session. :) Thank you oh-so-much for CVS.)

      --
      My other car is first.
    13. Re:inline code by OOGG_THE_CAVEMAN · · Score: 2, Insightful

      The failure mode of circular references defeating reference counting is more general than the toy example.

      It can very easily occur as one builds up complex data structures to make more abstract representations possible, and then using the abstractions in straightforward ways. Imagine embedding a table in an object, used to efficiently find neighboring objects in a network. If that network has any cycle in it, boom. What do you do if the user is the one building the network? Tell them not to use your tool for networks with cycles?

      This is analogous to the problems of manual memory management. In simple cases, i.e., simple enough to see the problem, you can always come up with a "simple" solution: i.e. "caller owns the resulting allocated object, and is responsible for deallocating." The problems develop when the call and ownership chains become complex, and the protocols built on top of protocols eventually fail to cover edge cases. Then, you've got a hell of a mess to crawl through to plug the leak.

    14. Re:inline code by Anonymous Coward · · Score: 0

      Oh boy. There's a lot of great advice in the comments on this story, but yet the most highly-moderated post is a frosh-level trick about mixing C++ and Perl into the same file? Welcome to Slashdot.

    15. Re:inline code by Simon+Brooke · · Score: 1
      You do need to worry about memory leaks in perl, as it uses refcounting instead of garbage collection.

      Reference counting isn't instead of garbage collection, it is garbage collection. It has some problems, I admit - it can't reclaim circular structures - but all garbage collecting algorithms have problems. I very much like reference counting as a garbage collection algorithm, because garbage collection rarely if ever halts execution for perceptable time.

      --
      I'm old enough to remember when discussions on Slashdot were well informed.
    16. Re:inline code by Anonymous Coward · · Score: 1, Insightful
      Just because you can't read or write Perl proficiently doesn't mean that's a problem with Perl... check out Perl Best Practices...

      But one could make the same argument about C or C++, or even Visual Basic or assembly for that matter. An experienced coder applying discipline and good habits to a design problem is far more likely to produce a quality system than a newbie or a weekend hacker.

      Some languages seem to encourage good habits more than others. I know very little about Perl, but it's reputation in this area is infamous. "There's more than one way to do it" is pretty much the opposite of encouraging good habits. Just because it's possible to write stable software with a particular language doesn't mean that it's a great choice when stability is very important.

      My own feeling is that when stability is important, one should 1) use a familiar language, 2) use the best habits/practices, and most importantly 3) be willing to spend lots of time specifying and designing before writing even one line of code. Ideally, the specs should be such that one could turn them over to an outsider, and he/she could produce a working system from them. This is the way things are done in mission-critical embedded apps, and it does make a difference. Productivity undeniably suffers, but the benefits in code quality become very obvious.

    17. Re:inline code by peterpi · · Score: 1

      Indeed it was a contrived example, but you wouldn't have to add too much context to make it a very believeable real-world piece of code. At my previous employer I found myself tracking down a single cyclic dependency in very large (well, a few thousand small objects) sets of data. Large enough to dump it all out to a file and get a REALLY big pice of paper and trace it out by hand. The author had just slipped up in a single place. Maybe it was a maintenance fix done when the original subtleties had been forgotten. The thing that annoyed me was that it only took a single mistake to keep the whole structure in memory; We'd have been better off using malloc and free, or new and delete.

      But anyway, I do agree with the message of the original post; write the program in whatever is easiest and optimise the bottlenecks from that point.

    18. Re:inline code by Peaker · · Score: 1

      The good old "Perl doesn't suck because any language can be used well or badly" argument.

      Why is that statement not applicable with assembly, or machine code?

      You can write readable and maintainable code in almost any language. Some languages just try to make it terribly hard. Perl is one of them.

    19. Re:inline code by Peaker · · Score: 2, Informative

      Python uses a hybrid approach of refcounting + refloop-finding.

      A language that leaks memory in real use cases is just not good enough. A language that slows down execution for periods of time may be good enough. The difference is that the first impairs correctness, while the second does so to performance. While bad performance can be tolerated, incorrectness can't.

    20. Re:inline code by jrockway · · Score: 1

      Ah, the good old "The good old "Perl doesn't suck because any language can be used well or badly" argument." argument.

      Anyway, go ahead and write your whole app in C++. Just don't complain when some other company writes their stuff in perl and all your customers switch because their app has more features and fewer bugs. Case in point: RT vs. Clarify CRM.

      --
      My other car is first.
    21. Re:inline code by Peaker · · Score: 1

      C++? No thanks :-) I'd almost rather use Perl.

      I'd prefer to use Python, thank you.

  4. I'm gonna take a guess, but.. by Anonymous Coward · · Score: 5, Funny

    try not to de-reference any NULL pointers and you should be ok..

    1. Re:I'm gonna take a guess, but.. by Anonymous Coward · · Score: 0, Funny

      dammit, dammit, dammit!

      BRB

    2. Re:I'm gonna take a guess, but.. by arivanov · · Score: 5, Insightful
      Well... Someone modded this as funny. Wrong... It is the first comment so far I have seen on this article that comes anywhere near being insightfull.

      The secret of stable system design is designing from failure. Designing and implementing defensively. If you want to design an ultrastable system you start with the failure analysis for every component, following with failure analysis of modules and the entire thing as it grows.

      This in the world of C++ (and C for that matter) quite often means checking paranoiacally everything everywhere for NULLs before doing anything about it.

      Designing and writing from failure means that every system or library call should be assumed to fail first and all failures handled cleanly. This may be quite painfull because it usually requires the development of special tools like wrappers around malloc, file calls, etc that return error conditions which are nearly impossible to achieve on a live system.

      Only after all codepaths for "bad" results have been handled, the actual "normal" codepaths should be written. This unfortunately is not the way code is written in 99% of the shops out there. Most design and implement from success first and add failure handling later.

      Just ask in your shop: "Where is our memalloc wrapper that simulates a failed memory allocation? I need to link versus it to do some testing to see how our app handles NULLs in a few places". The usual answer you will get is "Ugh? WTF you are talking about Dude... We do not smoke that stuff here... Just go and write the code you have been assigned to write..."

      And the results are quite bloody obvious.

      --
      Baker's Law: Misery no longer loves company. Nowadays it insists on it
      http://www.sigsegv.cx/
    3. Re:I'm gonna take a guess, but.. by Anonymous Coward · · Score: 2, Insightful

      I second that one.

      First rule of programming is You never disregard a return value.
      Second rule of programming is You never disregard a return value.

      If it can fail, you check and act on it. Event just to throw an error message and die. Usually, I undo all the things done before in the function. Then, when during testing someone comes back with an error message, the bug or problem (I deal with hardware, so bugs also occur in the FPGAs) can be understood in minutes, with no debugging session involved. For rarely occuring error that's precious. It's often advertised that catching a bug early save money, and you won't catch it earlier than by checking every goddam return value.

    4. Re:I'm gonna take a guess, but.. by ultranova · · Score: 1

      This in the world of C++ (and C for that matter) quite often means checking paranoiacally everything everywhere for NULLs before doing anything about it.

      Which does absolutely nothing against hanging pointers.

      If you need this level of stability, give up and use Java, because doing this much error checking means that your code isn't going to be any faster, and is going to be a horrible mess if you insist on doing it on C(++), and guarding against things like hanging pointers is simply impossible in C(++) - only a garbage collector with no manual memory freeing mechanism can guarantee that they won't happen.

      --

      Forget magic. Any technology distinguishable from divine power is insufficiently advanced.

    5. Re:I'm gonna take a guess, but.. by bcl · · Score: 1

      Interesting take on this can be found in http://www.cs.princeton.edu/~dpw/popl/06/Tim-POPL. ppt, slides from a POPL talk by Epic's Tim Sweeny. He is talking about what should be found in the next mainstream programming language but in doing so he brings some useful analysis of the Unreal codebase and discussing the kinds of programming errors that they find that sap productivity.

      That is one of the problems with the "it must be infinitely reliable": programmers have to make progress. Earlier someone suggested test-driven development. That is a really, really big deal. Then assume you are going to have to have a QA department that is bigger than the programming team.

    6. Re:I'm gonna take a guess, but.. by iangoldby · · Score: 2, Informative

      What you say is absolutely right, but we must remember that if you are about to try to dereference a NULL pointer, whether you check for NULLness beforehand or not, something has already gone wrong.

      This is why all of the comments about using a managed language are completely missing the point. Catching exception conditions before they terminate the process is great for tracking down bugs and for code that's allowed to recover from errors, but if you need error-free code, then you cannot afford to have these exception conditions in the first place.

      Your other point about checking all return values is 100% right.

      My own recommendation is to keep the code as simple as possible, and avoid anything that 'hides' code. Use OO design if you like, but be very wary of C++ constructs that might result in a whole load of code being fired off behind your back. This is especially true of operator overloading and temporary objects with their constructors.

      Do as little dynamic memory allocation as possible. Sometimes you can arrange things so that you know before you start exactly how much memory you'll need for everything and then allocate this all statically. Even consider accepting arbitrary limitations on data sizes if it helps achieve this and doesn't cost much in terms of flexibility.

    7. Re:I'm gonna take a guess, but.. by Anonymous Coward · · Score: 0

      No, the first rule of programming is "Whenever possible, steal code." =)

    8. Re:I'm gonna take a guess, but.. by runderwo · · Score: 1

      And from there, we arrive at the first rule of commercial software development, which is "Whenever possible, sue".

    9. Re:I'm gonna take a guess, but.. by null-sRc · · Score: 1

      try{}catch{}

      in every function! no more crashes yay!

      --
      -judging another only defines yourself
    10. Re:I'm gonna take a guess, but.. by Anonymous Coward · · Score: 0

      FYI, it's "insightful" and "painful." In fact every word of that form has only one L at the end.

    11. Re:I'm gonna take a guess, but.. by Anonymous Coward · · Score: 0

      Steve Maguire (in "Writing Solid Code") advises that programming this defensively can actually hide bad problems. Let's say there's a flaw in an algorithm. Crashing on a NULL pointer would alert the programmer and the problem could be fixed. What would handling the case of the NULL pointer give you other than hiding the error and possibly corrupting user data.

    12. Re:I'm gonna take a guess, but.. by HermanAB · · Score: 1

      I cannot agree more. The best way is to design a system such that it starts off in a state of failure and has to recover from this total failure in order to start up and run. Aircraft systems are typically designed this way.

      --
      Oh well, what the hell...
    13. Re:I'm gonna take a guess, but.. by Duhavid · · Score: 1

      You have kinda a point, but not handling the problem
      means that the error message will not lead you directly
      to a solution.

      Check for null, check return values, and DO SOMETHING
      with this information. If you cant recover, report.
      Then when it crashed in the field, you have something
      to go on, not a generic segfault report.

      --
      emt 377 emt 4
    14. Re:I'm gonna take a guess, but.. by Ed+Avis · · Score: 1

      You might also add - where possible, eliminate a particular class of errors by using libraries or a coding style that doesn't permit them. For example, in C++ use the standard string class rather than hand-rolling char[] arrays and fiddling with pointers. Use new, not malloc(), for allocating memory, since new will throw an exception on failure and most of the time this makes your 'failure path' easier to code and harder to forget.

      This may sound obvious but there is a surprising amount of C++ code out there littered with malloc() and pointers, and since programmers are fallible, also with pointer dereferencing errors. Have a look at Stroustrup's book and you'll see that he emphasizes using the safe standard containers like vector and list, using the string class for strings, and that pointer operations are hardly used at all in the early chapters.

      I completely agree that you should paranoidly check every return value when using functions that return a special value on error. Once you get used to this, you begin to appreciate more the value of libraries that use exceptions sensibly, or eliminate the possibility of certain kinds of error by not requring the programmer to deal with raw pointers or memory allocation.

      I would note, however, that on a typical Linux system malloc() will never return zero in practice; it merrily allocates more memory than your system has, and then your process will be randomly killed off later by the OOM killer. At least on desktops.

      --
      -- Ed Avis ed@membled.com
    15. Re:I'm gonna take a guess, but.. by phision · · Score: 0

      I agree with your points, but as you mention memory allocation errors, it reminds me of the "infamous OOM killer" in linux. This is a part of the VM code that assures the memory allocations always succeed and makes these checks unnecessary. I dont know if such tools exists on other operating systems, but i they do - my proposal is to make use of them.

  5. Performance? by rjstanford · · Score: 2, Insightful

    If you're willing to compromise performance to the point that you can use CORBA for IPC, then you should be more than willing to write it in the language of your choice, within reason. C, C#, C++, Java, all are far faster than your CORBA transport.

    If you can provide more details about the specific requirements, you might get more informed responses. As it is, though, your stated goals really don't seem to add up.

    Even as stated, I would write the core in a highly tuned fashion (although C++ might not be my best choice for this), then write the GUI in the language of your choice, quite frankly. Optimise the bottlenecks (ie: your core processing) for speed, optimise everything else for maintainability and ease of development.

    --
    You're special forces then? That's great! I just love your olympics!
    1. Re:Performance? by jeff_schiller · · Score: 1

      Wouldn't that depend on how much communication happens between modules?

  6. Development Practices by the+eric+conspiracy · · Score: 3, Insightful

    THere is no silver bullet for what you describe other than sound development practices. The best results in this area are acheived by teams who are constantly refining their processes based on lessons learned in previous software iterations.

    Bulletproof code isn't cheap, but it can be done.

    1. Re:Development Practices by ScrewMaster · · Score: 1

      Yeah ... the Space Shuttle software group pretty much exemplifies what it takes to write software that is about as fault-free as it's possible to get. And they work as you say, by sound development practices, and constant, never-ending testing and refinement. It's a grueling process but it works.

      --
      The higher the technology, the sharper that two-edged sword.
    2. Re:Development Practices by Coryoth · · Score: 3, Informative

      There are no silver bullets no, but there are tools that can help. Splint is a good example of something you can employ to make static checking for buffer overflows, and various dynamic memory errors like misuse of null pointers, dead storage, memory leaks, and dangerous aliasing in C and C++. It doesn't make your code bullet proof, but it can catch a lot of errors that you probably wouldn't otherwise spot. There's a nice paper about what it can do (warning PDF).

      Jedidiah.

    3. Re:Development Practices by LLuthor · · Score: 1

      Splint is absolutely useless with C++.

      For much better results, use Coverity on your code regularly.

      --
      LL
    4. Re:Development Practices by swillden · · Score: 3, Informative

      There is no silver bullet for what you describe other than sound development practices.

      True, but it should be pointed out that C++ is well-equipped to make such sound development practices easy. Consider the major sources of instability in C programs:

      1. Buffer overflows. This arises in C because you must allocate and use arrays for buffers. In C++, you should almost never allocate a simple array for use as a buffer in application code. For strings, use std::string. For collections of various sorts, used the STL collections. If you do actually need a buffer for some reason, wrap it in an appropriate class, keep it simple enough that you can easily verify every mode of operation and test the hell out of it.
      2. Dereferencing dangling or NULL pointers. There are several things you should do to avoid them:
        • Use smart pointers. Don't use naked pointers. Use appropriate smart pointer classes.
        • Don't create uninitialized pointers. At the very least, every pointer created should immediately be set to NULL if it can't be set to point at a valid object. Smart pointer classes can make sure everything is automatically NULLed.
        • Check memory allocations. Actually, on systems with virtual memory like Linux or Windows, memory allocations don't fail -- or, rather, if they do, you already have really big problems. It's a good idea to check anyway.
        • Check every pointer for NULL before dereferencing. This one is overkill for most applications, but if you can't ensure that your pointers aren't NULL, check them every time. If you use exceptions, have your smart pointers throw on a NULL dereference, but be warned that exception handling must be designed into your application from the beginning. It's hard to retrofit.
      3. Memory leaks. Other resources can leak as well. To avoid this, you should almost never explicitly free resources. Use "Resource Acquisition Is Initialization", which means that every resource you allocate should be immediately wrapped in an object whose destructor will free that resource (i.e. a smart pointer). If the memory you allocate doesn't have a simple lifetime (which is actually fairly rare, in my experience), use a reference counting smart pointer or similar.
      4. Incorrect library interface use. When you call library code, even if the library itself is solid and well-debugged, you have to use the library APIs as the library authors intended them to be used. Often, that means you have to violate the above recommendations. If the violations are too frequent and egregious, wrap the library in a layer that gives your application a cleaner API. If they're not too bad, just code all of the library calls carefully and review that code thoroughly. Above all, you *must* understand how the library APIs work, especially with respect to memory management and callbacks.
      5. Concurrency. Multi-threaded programming introduces a lot of weird and unexpected failure modes, at least until you really understand it. In general, most application code should avoid concurrency. However, there are some cases where it simplifies the code so much that it is a net win[*]. In those cases, all I can say is: code carefully, and make sure you know what you're doing.

      In my experience, doing the above religiously will ensure you never see segmentation faults. The next step, of course, is to make sure your code correctly implements the desired functionality. C++ is no different from Java or any other OO language in this respect. Clear rquirements definition, modularity, clean separation of concerns and testing, both automated an manual, are the basic keys to generating correct and maintainable code in any language.

      [*] A story: I once asked a guy on my team to write a little program to monitor a bank of modems, accepting incoming calls and exchanging data with the callers. He spent two weeks and produced nearly 10,000 lines of code

      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    5. Re:Development Practices by xyombie · · Score: 2

      Actually, splint doesn't support C++. But there is another product called Flexelint from gimpel.com that does the same thing, but for C/C++. Unfortunetly, Flexelint is not open source.

  7. Here's your best bet. by neo · · Score: 5, Interesting

    1. Write the whole thing in Python.
    2. Once it's bullet-proof, replace each function and object with C++ code.
    3. Profit.

    1. Re:Here's your best bet. by jellomizer · · Score: 1

      Using python as a prototyping language what a concept!
      Plus you are also able to include c++ libraries in python too. So after you get it to work you can replace each python module with the c++ ones and still make sure the app still works.

      I tend to do most of my programming in python for proof of concept even if it takes hours to run the code at least I know the concept works or not. If it does then I go into optimizing in a higher level language.

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    2. Re:Here's your best bet. by beyonddeath · · Score: 2, Informative

      Wouldn't you want something thats lower level? Im not even sure theres much higher a language than python!. perhaps you need to revisit csc108 (into to comp sci).

    3. Re:Here's your best bet. by YGingras · · Score: 5, Informative

      This is really good advice but it needs more details:

      1) Wrap your legacy libs with SWIG
      2) Code a working prototype in Python
      3) Profile it (never skip this step)
      4) Use SWIG to write the bottle neck parts in C++
      5) Use Valgrind to ensure you are still OK memory wise
      6) Profit!!

    4. Re:Here's your best bet. by Daxster · · Score: 1
      If it does [work] then I go into optimizing in a higher level language.


      I think you meant lower-level language ;-).
      --
      Death by snoo-snoo!
    5. Re:Here's your best bet. by jellomizer · · Score: 1

      Sure there is. VB.NET.
      I did mean lower level/ higher performance its late and I am tried.

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    6. Re:Here's your best bet. by Chandon+Seldon · · Score: 2, Informative
      I'll have to back up the start with python plan.

      Two additional points:
      1.) You don't need to replace all the python code.
      2.) Use a garbage collector like http://www.hpl.hp.com/personal/Hans_Boehm/gc/ for your C++ code.

      --
      -- The act of censorship is always worse than whatever is being censored. Always.
    7. Re:Here's your best bet. by play_in_traffic · · Score: 1

      Your simple and concise reply reminds me of the underwear gnomes in South Park. Why not write the whole thing in Fortran. The compliers and development tools are well tested. The only reminaing problem is to get your code right :-)).

    8. Re:Here's your best bet. by thinkliberty · · Score: 1

      You almost have it right, but left out the coffee step...

      You will never make it to step 3 without lots and lots of coffee.

    9. Re:Here's your best bet. by nairb774 · · Score: 1

      Intresting that python and reloadable modules come up...I have been working on a project that sets up Python so that modules can be started, stopped, and reloaded all live. I also make use of the garbage collector to unload modules while they are stopped. I can change some code, hit a button on a web page (yes it has a running web server plugin) and the plugin that was modified is reloaded updating the code while the rest of the parts continue to run. Talk about live coding. There is some unique wizardry behind the code. Now where is sourceforge when you need it...found it...now time to publish the idea...

      nairb774

    10. Re:Here's your best bet. by Anonymous Coward · · Score: 0

      So you are apparently claiming that it is more efficient to transform Python code to C++ code than to just write it in C++ in the first place? Why?

      Don't you think that the process of converting it may introduce some of the most subtle and difficult to fix bugs?!?

      This is a methodology problem, not a silver-bullet "use language X cause it's cool" problem.

      The steps are easy:
      Hire good coders. Figure out what you need before you build it. Follow a strict development & testing methodology. Conduct code reviews often. Keep you team happy & motivated. Profit.

      Executing them is hard.

    11. Re:Here's your best bet. by horza · · Score: 1

      1) Wrap your legacy libs with SWIG
      2) Code a working prototype in Python
      3) Profile it (never skip this step)
      4) Use SWIG to write the bottle neck parts in C++
      5) Use Valgrind to ensure you are still OK memory wise
      6) Profit!!


      I'd tweak that slightly to get going more quickly:
      1) Dump example output from core C++ functions into text files
      2) Code a working prototype in Python using dummy functions that simply read those text files
      3) Use SWIG to wrapper your core C++ functions and replace dummy functions
      4) All other steps YGringas mentions

      This means if you hit an unpredictable-appearing bug towards the end of the prototype development, you aren't left wondering whether the bug is in the Python, the SWIG wrapper, or the core C++ library reacting to some previously unencoutered encoding you are passing it.

      Phillip.

    12. Re:Here's your best bet. by Anonymous Coward · · Score: 0

      Aww. Come on, Yannick. We all know they should use Common Lisp.

      Je suis déçu de toi!

    13. Re:Here's your best bet. by njh · · Score: 1

      You are suggesting writing ultra-reliable code in python?! Python is fine for whipping up a quick toy, but for large scale applications it easily becomes unmanagable. I'd agree if you'd suggested a high level language like haskell first, but python's lack of static checking (of anything) makes it a very dangerous language for serious work.

    14. Re:Here's your best bet. by YGingras · · Score: 1

      You are right but I still haven't found a way to say this on /. without being modded down into oblivion as a troll... If we can introduce him to functional programming, he will find Lisp by himself.

    15. Re:Here's your best bet. by neo · · Score: 1

      I'd agree if you'd suggested a high level language like haskell first

      Haskel? If he wanted to write his own language he wouldn't be using C++.

    16. Re:Here's your best bet. by njh · · Score: 1

      I'm sorry, I don't understand your point? Haskell is a programming language, like C++.

      http://www.haskell.org/haskellwiki/Haskell

    17. Re:Here's your best bet. by Anonymous Coward · · Score: 0

      He was alluding to the fact that languages like Haskell are commonly used to write OTHER programming languages.

    18. Re:Here's your best bet. by njh · · Score: 1

      C is used to write operating systems, does that mean all C programs are operating systems? That seems a rather confused line of reasoning...

  8. They Write the Right Stuff by Pentclass · · Score: 5, Interesting
    1. Re:They Write the Right Stuff by blair1q · · Score: 2, Informative

      The accurate part follows all that bullshit about 9-to-5 droids.

      You can still be a balls-out code-monkey if the verification-analysis-requirements-code loop in your organization is well designed.

      The part about blame is important, too. The fact that gangs of humans are applying a vast store of partially-learned rules to a purely imagined set of requirements through a skein of lossy transmission lines with any number of distractions means that noise is inevitable, and in something as literal as code for Von Neumann machines, any noise means error.

      So it's not your fault, as long as you're honest about it. And if people accept that, you won't try to hide things, and that means the feedback processes will work to iteratively smooth out the kinks until the entire feature space and code set is 100% covered by correct functionality and test.

      Assuming all of the requirements are valid, for which there are only heuristic tools and few guarantees...

    2. Re:They Write the Right Stuff by Anonymous Coward · · Score: 0

      Second that.
      bug-free software is possible if every function is tested as soon as it is written, because you will never be able to test when you have 10 functions pending for unit testing.
      Have written mission critical software for stock exchanges, where every bug directly results in financial loss (and sometimes far reaching macro-economic mess).
      The only way to write ultra-stable code is to write less code, and more tests. And test it as soon as a code block (function/method/procedure) is written. same day. If anyone has a productivity of more than 100 lines of code per day, suspect the quality of that code.

    3. Re:They Write the Right Stuff by James_Aguilar · · Score: 1

      "Act like a grownup?" Yeah that is some good advice right there. It sounds like journalistic BS to me, when it comes right down to it.

    4. Re:They Write the Right Stuff by firewrought · · Score: 1
      The fact that gangs of humans are applying a vast store of partially-learned rules to a purely imagined set of requirements through a skein of lossy transmission lines with any number of distractions means that noise is inevitable, and in something as literal as code for Von Neumann machines, any noise means error.

      That juicy description just earned you a place on my friends list. Thanks!

      --
      -1, Too Many Layers Of Abstraction
    5. Re:They Write the Right Stuff by firewrought · · Score: 1
      It sounds like journalistic BS to me.

      No kidding... the NASA article is interesting, but the smugness is unwarranted and irritating. 260 staff, 20+ years, 420k lines of code??? That's some costly code. Good luck trying that in the real world... an OSS clone of your competitor's product will be in Debian Stable before you make it to the store shelves.

      When a journalist pull this type stunt, I think we should turn it around. For instance, let's hypothesize that there's a top-notch research paper on particle physics out there which took a team of grad students and PhD's a few years to create. The data for this paper was gathered and collated meticulously; evidence was assembled with great care along cautious lines of reasoning; pre-existing work from others in the field was carefully dug up, reviewed, applied to the problem under study, and referenced appropriately; assumptions, simplifications, and biases were clearly disclosed; the conclusions of the paper were carefully crafted to say only what was defensible; potential weaknesses were carefully pointed out and mitigated; avenues for additional research and open questions were pointed out; the results said something profound and helped others. What an achievement! Surely this is the future of journalism! That old tired image of the lone sloppy magazine writer hastily struggling to meet his deadline will be just a bad memory! Economic naivete, misuse of statistics, and one-size-fits-all mentalities will never make their way into print again! Yay!!

      --
      -1, Too Many Layers Of Abstraction
    6. Re:They Write the Right Stuff by Anonymous Coward · · Score: 0

      From the article it sounds like the development group highlighted in the article (the 'on-board shuttle group') is not 'grown up', but simply not under the pressures of the market. Time to market is increasingly important in software engineering. From the article, those who work in the 'on-board shuttle group' have the leisure to work 9-5. Of course if you work on a shuttle that hasn't changed markedly in 10 years, you're bound to have plenty of time - extra time to re-test code, extra time to catch bugs. In the article, one member of the referenced development team complains that a company he was working for outside the 'on-board shuttle group' development team simply wants a process to work - and they do not particularly care about the process as long as it works, is done, and is done fast. Yes, they wanted you to put the code out the door - they need to product to work, and they need to beat the competition there. 'Grown up' development team? No, simply a development team that does not have to push to hit market-stimulated deadlines.

    7. Re:They Write the Right Stuff by alphafoo · · Score: 1

      Debian Stable? With numbers like that, you're talking Duke Nukem Forever II, which is scheduled to release around the time our sun goes nova.

      It's funny to see people lump all software into the same category of criticality, as this journalist does. Sometimes, software development should be treated with much more care than it is. But sometimes, much less. Before one goes about writing any software of any kind, it makes sense to find out where you are on the spectrum and get that squared away, because ultimately it will answer every question the development process puts to you.

    8. Re:They Write the Right Stuff by lasindi · · Score: 1

      Thanks for the link to that very interesting article.

      That said, I think that following the shuttle group's practices is only a good idea up to a point. As the end of the article says, such a methodical, careful process is very expensive in terms of both time and money. For stuff that must absolutely, never ever fail (like the shuttle) this is is appropriate. But almost no software lives under such requirements. I'd rather have, say, a full-featured media player that can play lots of formats and has lots of features that might crash every now and then, than a program that plays a single WAV file every time without fail.

      Now, the submitter's program probably falls somewhere in between. People aren't going to die if his program fails, but crashes will be significantly more costly than having to double click your media player launcher. The article suggests he's working on this project alone, so having a whole other team looking over and testing his code probably is impractical, but if possible some kind of peer-review would probably help. Maybe blueprinting how the program works would be a good idea, and definitely having some kind of database on the code, i.e. version control like Subversion, is practically necessary for almost any major software project.

      The reason why programmers perhaps aren't as rigorous as other kinds of engineers in their design is because software is much easier to modify and fix (usually). If you're an architect building a building, you can't just move a beam from here to there, "recompile," and see what happens. In software, you can usually make a change, rebuild it, and try it out within a matter of seconds; that's that's rare if possible at all in other possible. An exception to this is the shuttle group, since they get only one shot.

      Anyways, all I'm saying is that programmers are generally sloppy because they can get away with it. This particular group can't, so they are very careful. The submitter can learn some from the group, but their methods shouldn't be seen as the holy grail of software development.

      --
      I have discovered a truly remarkable proof of this theorem that this sig is too small to contain.
    9. Re:They Write the Right Stuff by dghcasp · · Score: 1

      Thanks for reminding me of that article. It's quite good.

      However, it leaves to the very last paragraph something that limits its generality:

      • There is only one piece of software,
      • that only runs on one hardware configuration,
      • which is operated by highly intelligent people,
      • who understand the importance of detailed requirements analysis,
      • who have the same goals (reliability & defect avoidance) as the software team.

      In other words, their world is a little different than writing shrink-wrapped software that will be discarded in six months, and has to run on every PC hardware configuration out there.

      Or, "Never underestimate the effect a different serial card can have on your software, especially if your software doesn't use a serial card."

    10. Re:They Write the Right Stuff by canuck57 · · Score: 2, Insightful

      Follow NASA's advice... http://www.fastcompany.com/online/06/writestuff.ht ml [fastcompany.com]

      Your post should have been ranked informative +10 and is underrated. Those that think they are "professional" programmers aught to read this and memorize it. This thread has so much BS about what is right for making code stable it just shows how many poorly qualified people there are out there. But for other readers---

      I have been in both kind of shops, dime a dozen out of control cowboy mentality workshops, and a few others with high standards in planing, process, controls and testing procedures. The later produces better software that is not only less flawed and runs better, but costs less in the long term as you don't need an army to program it or to support it's quirks.

      Lets dispell some myths:

      • At minimum, one hour of rational planning and engineering with save 100 hours of programming and 10000 hours of support.
      • Bad code is bad code, it does not mater if it is C, C++, Java, Python, C#, J# or whatever. Adding another langauge will add complexity but solve nothing. If you want to fix it you need a real software engineer and not a programmer.
      • 9 of 10 programmers are incompetant, at best. If they were compared to brick layers, 9 of 10 could not make a straight or vertical wall. Same goes for software managers. This is the real reason of outsourcing.
      • Those that do know how to code either work alone or in qualified shops with diciplined processses. The later being the best.
      • Most I/T shops have the incorrect attitude, "we are not going to kill people by rushing this, so quicly do it". The truth is they don't know how and are incapable of doing it right the first time and have come to accept the high maintenance costs associated with sloppy computing practices. As their user perception deteriorates, another reason to outsource.
      • Ever notice how I/T vendors bypass techs? Don't trust those who do. If you have a wizard on staff that is socialble, use them but don't abuse them or they will leave. If they are anti-social, loos them.
      • Management is shallow in their vision, look at the long term in team development and raising the bar of the quality of software products. There will be less to worry about when you sleep.
      • The act of making the programming changes should be mechanical, repeatable and quick if planning and engineering are functioning correctly. If your programmers need spend more than 8 hours overtime per month your engineering and planning needs development. Also, if you have more programmers than engineers your resource base is out of whack.
      • Want to manage your project for success? Work the process not the technology.
    11. Re:They Write the Right Stuff by Anonymous Coward · · Score: 2, Insightful

      You have it correct. I worked in the GN&C FSW team this article describes from 1989 to 1994. I wrote code under an ever changing and improving process with a team of excellent managers, requirements analysts, peer developers, and Level1/2 testers. Generally, we worked 8 hours a day together. Overtime **was** the exception. Generally, our families got together outside work at least one night a week for softball, basketball, vollyball, or "off site team building" .

      In the real world - I work in telecom now - the idea of what a "bug" is, is completely different than what the GN&C guys thought a bug was.

      I've worked in places where everyone is fanatical about quality and even a memory leak found in your code what considered a failure to a place where accelerator keys where never tested because the gui coder and tester only used mice. The accel keys worked as a fluke, not as a rule. That code crashed constantly, except on the GUI programmers' machine. He always said, "it works on my machine." Like that is useful to a customer.

      High quality and productivity standards, repeatable processes and schedules, and "being careful what you measure, because that is what you'll get" is what I learned from my GN&C experience. At the time, I didn't realize it, but that was probably the best job I've ever had. Except for the paycheck, that is.

    12. Re:They Write the Right Stuff by try_anything · · Score: 1

      You're completely wrong about blame. A responsible boss will treat errors and slowdowns with a heavy dose of lecturing, rambling, and war stories. Remember, whatever the shortcoming is, the cure is for the implementers to study at the knee of the manager and become more like him.

    13. Re:They Write the Right Stuff by dodobh · · Score: 1

      Interestingly, _everyone_ I know who works at one of those process driven shops is in the 9/10 category. The best people either resufe to work for those shops, or walk out within a year because they can't stand the process.

      It isn't the process that makes people successful, as much as the people who make the process a success.

      And perhaps you should give a suggestion on how to deal with changing requirements as well, when those changes do involve considerable rethinking of the application?

      --
      I can throw myself at the ground, and miss.
    14. Re:They Write the Right Stuff by Anonymous Coward · · Score: 0

      And perhaps you should give a suggestion on how to deal with changing requirements as well, when those changes do involve considerable rethinking of the application?

      Excessive change requirements means the business analysis was flawed and incomplete to begin with, blaming the programmer is a self denial in such cases. While there will be those that play chichen in the high tech game, the bottom line is not caffein/hype, it is profits and deliverables.

      Too much BS in this tech business, I make money shorting it.

    15. Re:They Write the Right Stuff by blair1q · · Score: 1

      >Remember, whatever the shortcoming is, the cure is for the implementers to study at the knee of the manager and become more like him.

      I detect sarcasm.

      If none is meant, then it should be.

      Software managers are, to a man, lacking in applicable skill, or they'd still be using their skills.

      See, it's not the manager that teaches, it's the guru in the corner.

      Most of them understand that. Many don't.

    16. Re:They Write the Right Stuff by dodobh · · Score: 1

      Excessive change requirements means the business analysis was flawed and incomplete to begin with, blaming the programmer is a self denial in such cases

      I am not speaking about excessive change. Business environments change. Some projects take time to implement (think ERP). What happens when business requirements change during the implementation period? It may be something as simple as new reporting requirements (think SOX) leading to a lot of changes for access tracking.

      Saying that this should have been in place is fine, but legal requirements can force changes in implementation schedules.

      The shuttle design has been constant for quite sometime. If newer shuttles were being designed every few years, and the requirements changing from supporting a few people to say, supporting a couple of thousand people in orbit for a decade or so... Or even requiring that food be grown in hydroponic farms onboard and that the entire environment be controlled so that the people stay physically and mentally healthy.

      The shuttle software works in a relatively stable operating environment with known parameters. Most commercial software works in varying operating enviroments, with different parameters per user. There is a lot more complexity in a PC than the space shuttle, and lesser budget.

      --
      I can throw myself at the ground, and miss.
  9. For starters: by Bluesman · · Score: 1

    You can use the Boehm garbage collector to eliminate a huge class of typical memory errors:

    http://www.hpl.hp.com/personal/Hans_Boehm/gc/

    This isn't necessarily something you'd have to design around, either. You can add it later.

    --
    If moderation could change anything, it would be illegal.
  10. You need three things by hsmith · · Score: 1

    Good people
    lots of time
    lots of money


    then you have a chance of pumping out the good product

  11. Don't get too fancy... by Pyromage · · Score: 4, Informative

    First, consider how complex you want to make the system. The decoupling is a good idea, I think. However, I don't think that having modules automatically restart one another is a good idea; it introduces a whole slew of other problems. At most I'd say use a watchdog process (principle of single responsibility).

    Furthermore, you're crunching large amounts of data, so I'm guessing batch processing. If you can have the application not be a server, then you simplify things a lot. Make it a utility that takes data on standard input and runs whatever analysis you need, and duct tape it together with cron or a simple program that watches for new input files.

    Also, I'd like to suggest that you consider whether other languages could be efficient for the task. For example, Java is pretty good numerically, and as far as your libraries go, see if you can use SWIG to generate JNI wrappers. Also, then you get Java RMI.

    Next, get them down to one platform. It's *way* easier to develop software with tight constraints on a single platform (versus multiple platforms). Investigate QNX: a reliable operating system (though admittedly quirky) with a beautiful IPC API. In any case, make sure you get a well-tested library with message queues, etc. You don't want to be using raw sockets; you could but that's just another pain in the ass on top of everything else.

    Last, figure out what the cost of a failure is. Getting that last few percent of reliability is very very expensive. Unless you're a pacemaker or respirator, the cost of failure is probably not as high as the cost of five nines of uptime.

  12. Don't code to impress. by jellomizer · · Score: 5, Informative


    When coding something that needs to be stable, you need to keep your ego aside and concentrate on the task at hand. Stick with tried and true methods don't go with any algorithm that you are not 100% comfortable with even if it makes the code less ugly. Be sure to follow good practices make many function/methods, and make each one as simple as possible, makes it easier to check each function for bugs when they are simple. Secondly document it like you never want to touch the code again (in code and out of code), you want to know what is going on at all time and the bigger it gets the larger chance you could get lost in your own code. When working in a team and you are in someone else's code document that you did the change.

    Next take into account what causes most Crashes.
    Bad/Overflow memory allocation.
    Memory leaks.
    Endless loops.
    Bad calls to the hardware.
    Bad calls to the OS.
    Deadlock

    If you are going to decouple modules keep in mind that you will need to do as much processing as possible with minimum message passing and allow for mirrors so if one system is down and other can take its place, without killing the network.

    For IPC I tend to like TCP/IP Client server. But that is because it tends to offer a common platform independence and allows for expansion across the network. Or try other Server Methods such as a good SQL server Where you can put all the shared data in one spot and get it back. But not knowing the actual requirements it may just be a stupid idea.

    I would suggest that you also ask in other places other then Slashdot. While there are many experts on this topic there are also equal if not greater amount of kids on there who think they know what they are talking about, or they have there ego in this technology/or method.

    --
    If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    1. Re:Don't code to impress. by Shadyman · · Score: 1

      > Bad calls to the OS. C++ App: "Hello? Is this Windows?" Windows: "Yes." C++ App: "I need to display a window." Windows: "Uhh.. A window?" C++ App: "Yes, a window. You ARE Windows, after all." Windows: [Crashes. Logic Error]

    2. Re:Don't code to impress. by BlindSpot · · Score: 1

      Secondly document it like you never want to touch the code again

      So, you mean no documentation?

  13. Check your code... by Anonymous Coward · · Score: 0

    before you even write it. I mean get your idea clear and then write the code.
    Check your input _always_ and get clear on error signaling. Any module can cause an error, but this thing should be efficently said to other modules so they can handle the error.
    Create an universal error trap that will catch any error you don't expect, process it and allow for further program run.
    That should do it.

  14. The weakest link in the chain by karmaflux · · Score: 1, Insightful

    Your program's only as stable as the "core libraries" your company wants you to use.

    --

    REM Old programmers don't die. They just GOSUB without RETURN.

  15. Uphill Battle by twiddlingbits · · Score: 1, Informative

    First, there is not a silver bullet design that makes a program 100% crashproof. Even if there was there would need to be the corresponding crash proof Operating System, which there really isn't. Linux and some Unixes have very high uptime (99.997%), as do Mainframe OSes, but Windows certainly is not normally in that category.

    To make your program as crash proof as YOU can control you should validate your requirements using Use Cases, minimize Design Complexity, use good C++ programming practices, and do extensive testing at every level using white box and black box testing techniques. Testing is key, and regression testing after changes is even more key. Don't assume fixing this didn't break that. Test with REAL data if you can. Test with invalid data so you will test your error handling, test at maximum usage levels to validate no memory leaks, resource contentions, deadlocks, etc.

    However, at some point things get out of your control, as you don't write the C++ system calls, or the compiler code, or any OS features the code uses. So bugs in those can cause your program to crash. It wasn't your code that crashed but you'll get the blame. So to be crashproof it takes a "system" that is crashproof, you program is just one part of that.

    1. Re:Uphill Battle by Cheapy · · Score: 0

      "Linux and some Unixes have very high uptime (99.997%)"

      99.997 percent of what? Context!

      --
      Would you kindly mod me +1 insightful?
    2. Re:Uphill Battle by slazar · · Score: 1

      It's called uptime dumbass. 100% uptime is up all of the time. 99.997% is just a little less than that. uptime is the unit.

    3. Re:Uphill Battle by Anonymous Coward · · Score: 0

      You don't know what uptime is, yet you still nitpick.

    4. Re:Uphill Battle by Cheapy · · Score: 1

      Well gee, here I was thinking that uptime was measured in time. I'm sure it's a common mistake though; I mean you only see geeks going "I have an uptime of 42 days and 37 seconds!", not "My uptime is 99.975%!"

      --
      Would you kindly mod me +1 insightful?
    5. Re:Uphill Battle by Anonymous Coward · · Score: 0

      That's ok. Here's a homework assignment for you. Use Poison's distribution to relaton uptime in seconds to uptime in %. Hint: the uptime in seconds is just on instance of the overall estimated uptime.

    6. Re:Uphill Battle by slazar · · Score: 1

      Ah but with a company offering a service, they often talk about how many nines they can offer. Five nines is a common target. Here, let me help.
      http://www.google.com/search?q=99.999

  16. Question from a Newbie by Anonymous Coward · · Score: 0

    Given the advice you are giving the original poster, would the D programming language be a good alternative choice for him? Programming by contract, binary compatibility with C libraries, and actually compiled as CPU instructions.

    1. Re:Question from a Newbie by inter+alias · · Score: 2, Informative

      Funny you should that, I read this: D just 5 minutes ago.

  17. Use state machines by Warlock48 · · Score: 2, Informative

    State machines help make sure you cover (almost) all possibles cases your app may encounter.

    Here's a great framework to start with:
    http://www.quantum-leaps.com/products/qf.htm
    And the book:
    http://www.quantum-leaps.com/writings/book.htm

  18. XP by joebebel · · Score: 1

    Extreme programming is your friend on this one. Doesn't matter what language you use, test and retest at every change. Testing is the only, only, only way to get extremely stable software outside of formal verification methods.

    1. Re:XP by Anonymous+Brave+Guy · · Score: 3, Insightful

      Extreme programming is your worst enemy on this one. If you need a system that is truly reliable, you cannot take an approach that fundamentally bases its quality controls on a finite number of tests, unless you can test absolutely every possible set of inputs your program can ever receive (legitimately or otherwise).

      Testing is good, of course, but for this sort of job, you must have a proper design, such that all components can be properly verified. (And of course, you must have a proper spec against which to verify.) The XP methodolgy is pretty much the antithesis of what's needed here.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    2. Re:XP by Fulg · · Score: 2, Informative

      Extreme programming is your friend on this one. Doesn't matter what language you use, test and retest at every change. Testing is the only, only, only way to get extremely stable software outside of formal verification methods.

      Exactly. Three words: Test Driven Development.

      Since you're tied to C++, may I suggest CppUnitLite2 1.1...

      It's incredible how much more productive you can be writing the tests first (contrary to what you might think initially). I hardly ever need a debugger anymore, and I know that the code I wrote does the right thing, and doesn't adversely affect something else.

      Put the unit tests as a post-build step (or a dummy target in a makefile) and any defect will pop up instantly. If you find a bug not covered by your test suite, add a test that reproduces the problem, ensuring that it will never bite you again.

      If you're not familiar with TDD, check out Wikipedia for an explanation and some useful external links: http://en.wikipedia.org/wiki/Test_driven_developme nt

      --
      gcc: no input sig
    3. Re:XP by joebebel · · Score: 1

      Having a design is worthless unless you develop a series of tests against it. Even the best designs by the best software engineers have flaws, and if there aren't, some flaws will pop up in coding. You can have a perfect design and crummy code, I've seen it over and over again.

    4. Re:XP by Anonymous+Brave+Guy · · Score: 1

      Of course proper unit tests are necessary; I wouldn't dream of suggesting otherwise. My point was simply that for this kind of project, they aren't sufficient. The XP approach inherently assumes that they are, and is fundamentally unsuitable for this type of work.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    5. Re:XP by Anonymous Coward · · Score: 0

      I agree ten-thousand percent (no exaggeration!) for all the reasons listed. Don't let a user test your software with garbage data before you do.

    6. Re:XP by Anonymous Coward · · Score: 0

      rubbish. XP and TDD are fine to get 'relatively' stable software delivered 'relatively' quickly - relative to what happens in your average development team that uses no structure or something traditional.

      they were never meant to replace methods used by serious stability-oriented teams, because they focus on tests, whereas 100% stability people focus on perfect processes which they then test or, if they can, prove. You have to do it this way because you can't limit your tests, and if they're unlimited, then they are easier to write and the focus goes back on design & quality implementation processes again.

    7. Re:XP by Anonymous Coward · · Score: 0

      XP isn't about doing more or "better" testing. It's about what the tests are *for*. In XP, the idea is that you make the tests part of the specification process - you're driven to what to write by the tests.

      This is quite a neat idea, but you don't end up with something that definately works 'better' or is more stable or fault-tolerant. That isn't what XP (or rather test-driven dev part of XP) addresses.

      Test-diven dev is a specification method and a code development approach. It is *not* a test, proof or system validation method. If you don't clearly understand that, and rely on TDD to get you a stable system by default with no further effort required, you're going to get a nasty surprise one day.

    8. Re:XP by Hortensia+Patel · · Score: 1

      Well put. We've found agile development to be a very effective way to build reasonable-quality software, for surprisingly high values of "reasonable", but as you say it's absolutely unsuited to building lots-of-nines software.

      Of course, very few customers actually want lots-of-nines software, where "want" means "are prepared to pay for".

    9. Re:XP by Anonymous+Cowhead · · Score: 1
      Of course proper unit tests are necessary; I wouldn't dream of suggesting otherwise. My point was simply that for this kind of project, they aren't sufficient. The XP approach inherently assumes that they are, and is fundamentally unsuitable for this type of work.
      XP does not assume unit tests are sufficient. Your opinions are fundamentally unsuitable to be followed for this type of work.
    10. Re:XP by Anonymous+Brave+Guy · · Score: 1
      XP does not assume unit tests are sufficient.

      Of course it does. The whole philosophy of XP is based around the idea that the unit tests effectively become the specification. It is expected that code will be refactored often, assumed that this must produce the correct results as long as the unit tests still pass, and intended that any such refactorings be released quickly and in small chunks as long as the tests do still pass. To XP, the idea of having a big picture design that is planned out ahead of time is an anathema; it should be unnecessary, since the tests should ensure that everything always gives the correct results. In XP, there is no detailed specification ahead of time; you write the initial tests to get started, and then develop further tests in consultation with an ever-present customer. The problem with all of this is that the assumptions are only valid if you have an exhaustive test suite, and if having a customer rep on-site who makes decisions on the fly is sufficiently well-specified to guarantee completeness and correctness of specification.

      Consider the simple example of a program that calculates the square of an integer. This can be formally specified with a few mathematical symbols on a single line. The code to implement it could be rigorously analysed to identify ranges over which the inputs would be accepted and correct outputs given. In general, this will be time-consuming, but such is the price of having truly reliable code. How many unit tests would an XP team have to create to get the same guarantees?

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    11. Re:XP by Forbman · · Score: 1

      The code to implement it could be rigorously analysed to identify ranges over which the inputs would be accepted and correct outputs given.

      But, don't you still want to test it against inputs which aren't acceptable, to make sure that the code deals with the situation appropriately (throws a handled exception, etc)? So, you're still writing tests to verify expected inputs are handled correctly (i.e., return correct value), and incorrect inputs are handled gracefully.

    12. Re:XP by Anonymous+Brave+Guy · · Score: 1

      Of course I would still write tests. They're an extra safety net. But I won't need them to tell me what happens when an "invalid" input is being handled, because either I'll know exactly what happens for that input, or I'll know from the verification of other components that it can never happen.

      The point is really that in everyday programming, you can "know" that something's "impossible", and yet it still happens sometimes because of bugs. In the kind of world we're walking in here, there's so much rigorous checking going on before we even get to the point of running any code that the odds of that happening are vanishingly small.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    13. Re:XP by Anonymous+Brave+Guy · · Score: 1

      Indeed. But, as the saying goes, you do get what you pay for.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
  19. HR by Blue+Mandelbrot · · Score: 1

    I think the people you have working on this particular project will have the most influence on whether you have a stable design in the end; especially when working with C++. Put together a team of top-notch engineers, read the Mythical Man Month, then start to think about the design. If you gave three different teams the same task, most likely in the end these three teams would produce three different, yet functional designs; with one of these designs being the most stable. The success of many large projects hinge on the skill set of the engineers, communication, project management, and process (CMM, etc.).

    1. Re:HR by Anonymous Coward · · Score: 0

      You've just tripled the development cost.

  20. What's important? by mr_tenor · · Score: 1

    You talk about making an "ultra stable, crash free" ystem and then talk about crash recovery. I'm guessing from this you don't want to protect the application from harm (eg. full of exception catching and internal recovery from those evil buggy 3rd party librariesor whatnot), but how important is your data? Is that what you mean when you mean ultra stable, that you end up getting the right results at the end? Maybe you should think about redundancy, tracability of results etc.

  21. Fault Tolerance Vs. Stability by aeroz3 · · Score: 5, Insightful

    I think perhaps what you REALLY mean here by stability is Fault Tolerance. It's impossible to write code that has zero defects, outside of any trivial examples. Real Code Has Real Defects. Now, as you talk about modular design and being able to restart modules, you're talking about, not stability, but fault tolerance; the ability of the application to recognize and recover from faults. For instance, you can't necessarily guarantee that the module on machine A running task B won't die, hell the computer could accidently fry, but if your application was Fault Tolerant then the application would kick off another process somewhere else on computer C to rerun job B. Stable systems aren't built necessarily by trying to write defect-free code, but by recognizing that defects will occur and architecting the system in such a way that it can recover from them. Here you need to be concerned about things like transactions, data roll-back, consistency, techniques (active vs. passive, warm vs. cold). The key thing is before you even write a LINE of this C++ code, make sure that you have a complete, comprehensive ARCHITECTURE for your application that will gracefully handle faults.

    1. Re:Fault Tolerance Vs. Stability by cjonslashdot · · Score: 1

      That is an excellent point. A stable program has to be resilient to fialure.

    2. Re:Fault Tolerance Vs. Stability by ivec · · Score: 1

      Agreed -- stability is more about fault tolerance by design.

      Key things to watch for IMHO are:
        - Keep things simple: don't multiply processes and communication layers for the sake of 'isolation'. Include a point of recovery (e.g. relaunch a process), but don't try to be too smart.
        - Use higher-level abstractions: proper use of smart pointers will keep most memory leaks away. I've had 1 identified leak in my last 7 years of coding in C++ (and I do look for them). Use containers. Use a debug-enabled implementation of the Standard C++ library if you can.
        - Use encapsulation: create your own abstractions, use module tests.
        - Make an upfront analysis of all possible failure modes: network failures, memory outages, data corruption, etc... Think how you will deal with an unrecoverable errors requiring external intervention. How will an administrator be notified? Can you alert preventively about a problem that is going to happen soon?
        - Study safe coding practices...
            [ running out of time now ]

      BTW: Java/.Net/Managed applications will crash too. The only thing they hopefully protect you from is memory corruption. This doesn't mean you'll always land into a recoverable state.
      Many very stable systems have been written in C/C++. All the managed infrastructures are coded in those languages as well.

    3. Re:Fault Tolerance Vs. Stability by Anonymous Coward · · Score: 0
      It's impossible to write code that has zero defects, outside of any trivial examples. Real Code Has Real Defects.
      This is not true. You can formally proof your program to be correct. Only it takes 10 times as much manpower than writing the software itself. That's why it is not done for most code because of time to market constraints.
    4. Re:Fault Tolerance Vs. Stability by twiddlingbits · · Score: 1

      GOod points, and all true. But the FIRST thing you need to know is "Is High Availabilty (fault tolerant) required or is it something a Manager somewhere thought was nifty? And if so, is it only single fault tolerant or multiple fault tolerant? If the answer is Yes, then Management needs to know how much this decision will cost. Often they will change their minds when that fact is known. This does not give a license to write poor code, all the techniques illustrated in this whole discussion have value to ANY software development project. As you mentioned there are several means of acheiving HA systems, each one has to be evaluated for applicability to the situation. Just as in Software Developement, there is no Silver Bullet Architecture that works in all cases.

    5. Re:Fault Tolerance Vs. Stability by GileadGreene · · Score: 2, Informative

      Wow. An entire thread devoted to this question, and so far this is the only answer that actually addresses the problem. Every other suggestions seems to be "changes languages", or "here's how to avoid bugs".

      Anyway, let's talk specifics here. For the theoretical end of software fault tolerance, you can get a quick overview here or here.

      In terms of practicalities, I know of an older fault tolerance library for Unix that includes watchdog, checkpointing, and replication utilities, and was created by AT&T (details and downloads here). A newer version appears to be available for Windows under the name SwiFT. Disclaimer: I haven't actually used either of these, and they both seem a little old. But I don't know of anything newer that isn't a proprietary in-house solution.

      Finally, in terms of general design patterns for fault-tolerant distributed systems, you can't go past Joe Armstrong's PhD thesis, "Making reliable systems in the presence of software errors". While it's mostly about Erlang, many of the ideas he presents are readily applicable to other languages too.

  22. be assertive by Anonymous Coward · · Score: 2, Informative

    be assertive

  23. Pretend you are writing code for an airplane... by smackenzie · · Score: 2, Informative

    ...that you are about to board.

    I've spent over a decade refining how best to create stable, great software. And guess what? I still learn things every day. If you are really new to enterprise-grade software, the best thing you can do is search amazon and choose 3 to 5 great books about writing stable, bug-free enterprise code and just start reading and scheming. Give yourself lots of time. Be neurotic, type-A, attention to every detail, stay up at night wondering how your system could fail and what you can do to prevent it. Some immediate thoughts, however:

    1. Good hardware. Obviously. Redundancy everything, self-diagnosing, etc. How can things go wrong? What will go wrong? How can I know when something is going wrong? How I can fix it quickly without impacting the system? Etc.

    2. Enterprise grade (n-tier) architecture: You'll definitely want to do something where you have a database running on one or two (or more) machines, at least two business servers and at least two web servers. Redundancy is good. As you suggested, a setup like this lets you isolate problems (and provides for better security in general).

    3. Test, test, test. From the very start, every day to the very end. Start coding by writing test suites for your code. Learn about unit testing, black box testing, user testing, regression testing, etc. And hire developers and QA whose sole job is test, test, test using great automated testing software.

    4. Profile. Stress-load-test. Know how your system responds to all scenarios. Feel comfortable knowing the limits of your system. There should be no surprises.

    5. Assert. Learn the magic of assert(). If your code isn't at least 25% asserts, you are not trying hard enough.

    I told myself I was only going to write the first five thoughts that came to my mind, otherwise I could spend weeks trying to answer your question!

    1. Re:Pretend you are writing code for an airplane... by Anonymous Coward · · Score: 0

      5. Assert. Learn the magic of assert(). If your code isn't at least 25% asserts, you are not trying hard enough.

      Very bad advice. All assert() does if an error condition is encountered is print a message and exit the application. That is hardly ideal for a production application. Consider the subject of your reply, 'Pretend you are writing code for an airplane...'. Should the application controling the airplane just print a stupid message and die when it encounters an error? If a condition is worth checking for with assert(), it would be better to check for it using 'if ()' and handle the condition properly. Worst case, you can exit the application after performing proper cleanup and shutdown like assert would have done. In many cases, it will be possible to recover without exiting the application. How many times do we have to put up with shitty applications printing cryptic error messages and exiting because some wanker decided to use assert() instead of handling errors like a grown up.

    2. Re:Pretend you are writing code for an airplane... by FryingLizard · · Score: 1

      That is a dumb reply. The asserts() make things stop instantly when the test suite touches a sore spot, hence making debugging much simpler.
      They are supposed to make things break, that's the point! - and break in a clean, logged, maximally reproducible way. Essentially they just indicate that things have already broken, and make it as obvious as possible to everyone, including the test harness (that does not have the benefit of such inside information as to the possible brokenness of things).

      --
      [FrLz]
    3. Re:Pretend you are writing code for an airplane... by Anonymous Coward · · Score: 0

      That is a dumb reply. The asserts() make things stop instantly when the test suite touches a sore spot, hence making debugging much simpler.
      They are supposed to make things break, that's the point! - and break in a clean, logged, maximally reproducible way. Essentially they just indicate that things have already broken, and make it as obvious as possible to everyone, including the test harness (that does not have the benefit of such inside information as to the possible brokenness of things).


      Your's is the ignorant reply. Asserts do not "make things break". They detect it when something has broken, and they handle that situation very, very poorly. Too many times the writer of a library function will do stupid shit like:

            p = malloc(42);
            assert(p != NULL);

      Far better to return an error code to the caller and allow them to handle the error as appropriate. The bottom line is that if there is any error condition that might occur in test, it needs to be checked in production, too. And having production applications go tits up on potentially recoverable error conditions is not acceptable.

    4. Re:Pretend you are writing code for an airplane... by smackenzie · · Score: 1

      Obviously, neither of you have a clue. First of all, assert() code is COMPLETELY TURNED OFF for a production build. You only use it for testing to guarantee all inputs / outputs / state changes, etc.

      Second,p = malloc(42), assert(p != NULL) IS a stupid idea because memory is a resource that _can_ be used up in a realtime production environment. In that case you want to use exceptions or error codes. In other words, use assert() liberally in your code for test harnesses for debug, but always use exceptions for something that can happen in real time. This is basic stuff, guys, and you shouldn't reply unless you've really used it in enterprise-grade production code. One of my current applications process millions of health care claims daily (multi, multi stage, ridiculous pipeline) where a single regular expression situation can cause a company to lose a tremendous amount of money. I use asserts(). I use exceptions().

    5. Re:Pretend you are writing code for an airplane... by Anonymous Coward · · Score: 0

      Obviously, neither of you have a clue. First of all, assert() code is COMPLETELY TURNED OFF for a production build. You only use it for testing to guarantee all inputs / outputs / state changes, etc.

      It is you who is clueless. If you are not "testing to guarantee all input / output / state" changes in the production builds, then you have no business writing enterprise software. It's a simple as that. You acknowledge that assert() is not intended for this task in production, so a competent programmer must include proper error handling code for it.

  24. Try ACE/TAO or ICE by Anonymous Coward · · Score: 0

    If you consider CORBA check out TAO (http://www.cs.wustl.edu/~schmidt/TAO.html), it is a reliable open-source implementation that is widely used. You can get commercial support for it from OCI (http://www.theaceorb.com./

    If CORBA is too heavyweight for you take a look at ACE (http://www.cs.wustl.edu/~schmidt/ACE.html). ACE is an open-source portable framework that is used within the TAO real-time CORBA. It allows you to write portable networked applications in C++ but is a lot smaller than CORBA as it does not implement the ORB etc. Several companies use ACE as a lightweight middleware as it has a very permissive license. You can get commercial support for it from Riverace (http://www.riverace.com/).

    If you're aiming for performance you might check out ICE (http://www.zeroc.com./ ICE is available under the GPL and commercially and is a really fast middleware that is not CORBA but is portable between several languages.

    All options provide you with a good framework to develop reliable and maintanable code.

  25. It's simple, really by eclectro · · Score: 3, Funny


    Use TPS reports. You'll thank me later.

    --
    Take the cheese to sickbay, the doctor should see it as soon as possible - B'Elanna Torres, "Learning Curve"
    1. Re:It's simple, really by chicagotypewriter · · Score: 1

      Be sure to use the new cover sheets on them.

    2. Re:It's simple, really by CptNerd · · Score: 1


      Wasn't there a memo about that?

      --
      By the taping of my glasses, something geeky this way passes
  26. Small code by Gyorg_Lavode · · Score: 1
    I heard once that the NSA would only certify software under 4,000 LOC. (I don't know if this is still true.) The reason was over 4,000 lines of code it became to complex to validate for highly critical systems. The person who told me this also stated that all of those old systems that have been running for ever that protect are nation were coded below this requirement. Some of them signifigantly under it.

    I don't know how complex your system has to be, but I'd strip out anything that isn't 100% necessary. No convenience code. No pretty, easy-to-use, fully featured gui. Just the basic required to get the job done. At that short a length you should be able to reliably verify a VERY low coding error/KLOC. Also, I would recommend 2-person coding if you have the say in it. Have 2 people working at the same time. 1 codes, the other checks. It will save yourself a lot when you go to testing and check out.

    --
    I do security
    1. Re:Small code by Anonymous Coward · · Score: 0

      "...it became to complex...", "...that protect are nation...", "Just the basic required to get the job done.", "At that short a length ..."

      Too bad you didn't follow your own advice -- with spelling and grammar!

    2. Re:Small code by ajdlinux · · Score: 1

      I would add on that you should not have a GUI or anything like that in the core program, but you must make sure that the program is scriptable enough to add one using another separate program, e.g. include an IPC system accesible from the outside to control it.

  27. You're already screwed from the getgo... by Anonymous Coward · · Score: 0

    It doesn't have anything to do with using C++, because you are ultimately at the mercy of how the libraries you're accessing are going to interact with whatever systems you're doing. Because you have that dependency you can make nothing rock solid without putting a strong layer of security between those libraries and you.

    If I were to make this as secure and stable as possible that's where I'd start - by wrapping those libraries in some strong error handling systems. Probably even go one step further and use some managed code wrappers (JNI, COM, CORBA, whatever) so that you can interact with the libraries using managed code. That will save you any number of headaches in the long run and will be immediately more testable, as you can separate easily the libraries you're using from the code you're writing and use stubs to test both fairly trivially.

  28. Another tool: Microreboots by pkhuong · · Score: 1

    In short, have each component loosely coupled with the whole system, and make each component crash and restart (to a recent good state) on failure. When shit happens the whole system can go on working, and the component that crashed resumes work quickly.

    c.f. http://crash.stanford.edu/

    --
    Try Corewar @ www.koth.org - rec.games.corewar
  29. Use formal methods by Anonymous Coward · · Score: 0

    Use formal methods. If you really need all of the things you mentioned, than I'm sure you client will be happy to pay the premium. Unless, like every other frakking client I've ever seen, they want it yesterday and for peanuts :).

  30. +5 Funny by amling · · Score: 2, Funny

    I wish I could mod the article +5 Funny.

    --
    70e808a22cb027cde4a6abddf6435d55
  31. Stability by nroose · · Score: 1

    At some level, the definition of stability is that it does not change often. Thorough testing is of absolute importance. Make sure every block of code is tested with a large enough variety of data. Once you have it in production, make sure you go after any problems that you have - never let any bug bite you twice. Don't add unnecessary features; keep it as simple as possible.

  32. Some simple rules... by SingleShot · · Score: 1

    I've been out of C++ programming for several years, but I do remember a couple basic rules I followed that saved me from a lot of memory problems and invalid state problems. This may not be the kind of thing you're looking for, but here it goes... 1) Never allocate memory to a raw pointer. Never. That is, if you allocate memory to something, it better be allocated to a smart pointer like auto_ptr or a reference counting pointer (boost.org at the time had a family of these). The only exception to this rule is in the implementation of the smart pointers themselves. You should be able to find a good number of articles on this. 2) Always follow the "strong exception safety guarantee". Classes that provide this guarantee promise that they will not change their state if they throw an exception. Again, there are many articles. Here's an example of an assignment operator providing the guarantee (please forgive me if my C++ is not quite right - I'm rusty): Whole::operator=(const Whole& that) { auto_ptr tempPart1 = new Part(that.part1); auto_ptr tempPart2 = new Part(that.part2); this.part1 = tempPart1; this.part2 = tempPart2; } The example is a class Whole with two dynamically allocated Parts. The assignment operator instead of having two lines of code - i.e. cloning the two parts and assigning them directly to the member variables - has four. It first clones the parts to temporary variables and then assigns them to the member variables. Why? Without the temporary variables, if the second "new" operation throws an exception (such as bad_alloc), the state of the class would be different and inconsistent from before the call. It would have one original part, and one part from the cloned class. There are lots of other simple rules like this that can make code more solid, easier to read, and easier to maintain. If I remember right, the C++ FAQ from the C++ newsgroup contains a lot of them.

  33. C++, automatics without limits will destroy you by jimmydevice · · Score: 2, Insightful

    If your develop safety critical code, or anything that requires hi-rel you need to break down the application into functional testable units, with test fixtures to test each module. Then a integration test framework. You can't create a "verified" correct system with ad-hoc testing. Unless you're very good and you own the whole thing and then it's just you that knows it's right, Ya right.
    JimD.

  34. obvious answer by cameronpurdy · · Score: 0, Flamebait

    > what strategies should a developer take to insure that the resulting program is as crash-free as possible? First, avoid using C++.

  35. A few tips off the top of my head by 3770 · · Score: 1

    *Get a coverage testing tool

    *avoid pointer arithmetic

    *declare your copy constructors private (with no body) if you don't plan to use them. With this you'll catch unintentional use of the copy constructor through parameter passing.

    *Use unit testing and make sure you can regression test your system

    *Get a tool such as purify to find memory leaks and use of uninitialized memory

    *turn on compiler warnings to its most anal setting

    *Create a system to give you a call stack in case of errors (to quickly squash bugs because you will have bugs).

    *Only write multi-threaded if you have to. If you have to program multithreadedly, try to have a good and well thought out strategy to avoid race conditions.

    --
    The Internet is full. Go Away!!!
  36. Know your client. by jellomizer · · Score: 1

    You sound like you are new at this, probably just graduated from college a few months ago. But I would suggest that you know your clients and what their expectations are. Every client will say that they need the application bullet proof and fast, and it is the most important program on earth.
    But what they really need is a simple solution that is better then what they currently have. This is not an excuse to write sloppy code. But to keep in mind what is needed. If you can get the job done in something simple do it. If you make it more complex then you need trouble will just occur in the future. If the program takes 100 minutes to run vs. 90 minutes. They will learn to deal with it. Remember It is often cheaper to buy a computer that is twice as fast then it is for the Programmer to write there code to run 10% faster.

    This sounds like an issue my friend from college was talking to me about when he first started working. The client wanted a High performance method of sending messages to the company and managing the data. So he spend months of working with low level programming calls to have almost working solution that did what the management said they wanted. Then what they really wanted was a mailto: link on the page, and have outlook filter the data.

    --
    If something is so important that you feel the need to post it on the internet... It probably isn't that important.
  37. Question your assumptions by Anonymous Coward · · Score: 0

    You say "for reasons of efficiency". How do you know that some other safer language (like Java) wouldn't be efficient enough? Have you done smoe tests? Have you analyzed the business case? The business case would look like this: "We could write it in C++, which would be efficient enough to run on Hardware X, or we could write it in Java, which would require more expensive Hardware Y. The cost difference between the two is Z, and the programming time to get the same level of safety between C++ vs Java is Q, so clearly it's a lot cheaper to do it in C++ and save money on the hardware."

    Most of the projects that worry about "efficiency" haven't done an analysis like this, and 99% of the time, if they did such an analysis, the would find out that they are blowing $50k in programmer-hours to save $5k in hardware.

    Then if you do another step of the analysis and put in a term like this: "A one-day outage or security breach could cost us $500k in lost business. Java has no buffer overflows, direct memory access or other common causes of security problems. Which is the cheaper option?"

    Optimize last, usually.

    I know, I hate it when I ask a question, "how do I do this with this certain tool" and someone says, "you shouldn't be using that tool", but, unless what you are doing is a ray-tracing cluster or similar, it sounds like you are on the wrong track.

  38. You are worrying about the wrong thing. by jefp · · Score: 0, Offtopic

    If you want an ultra-stable crash-free system, you will need to avoid both Linux and Windows. The choice of programming language and methodology is way down in the noise compared to that.

    Use FreeBSD or stay home.

  39. It's not the language that counts... by insert_username_here · · Score: 1
    it's how you use it!

    Honestly, everyone seem to believe that all C/C++ code is unstable (probably because of all those people working for companies like Sun/Microsoft, who are promoting The Next Big Thing in Software Development), but it's far more to do with how you go about using the language and its features.

    However, it is honestly an improvement on C. I think Bjarne Stroustrup (I'm almost certain I spelled that wrong) said it best: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." (http://public.research.att.com/~bs/bs_faq.html; apart from the quote, it has a whole lot of useful tips).

    So, here's my advice, from my experience working in all sorts of languages (professionally I've used everything from TCL through PHP to Java/C#, but at home I use C++ exclusively). This is just my experience, though; take this with the requisite grain of salt:

    STL is your friend. I cannot stress this enough. STL allows you to leverage complex containers (automatically resizing lists, hash tables, ropes - which are mega-long strings, etc) with complete type safety: you can create a container for a particular type, and the compiler will balk if you ever try to put something incompatible in. Also, the generated code will be optimized for your particular storage type. In this respect, C++ is actually better than most other languages (only with Java 1.5 and .NET 2.0 do Java and C# implement Generics, and in the case of Java, it's only implemented in the compiler).

    Pointers are not always your friend. When you allocate data structures on the stack (e.g. "string blah;"), they will automatically be taken care of by the language. Even if an exception is thrown, these objects will still have their destructor called (which in turn will call all other necessary destructors) and the memory will be deallocated freely.

    Of course, this will not work everywhere (large numbers of polymorphic, dynamically allocated objects). But in these cases, you can use helper classes (such as auto_ptr in the STL, or something like shared_ptr from Boost or nsCOMPtr from Mozilla). Look around; lots of other people have already solved this problem. In fact, there are even Garbage-Collection libraries available for C++!

    Use exceptions instead of value checking, dammit! Every time you call a function that "returns 0/false/-1 on error" you are exposing yourself to possible bugs. Try to avoid this wherever possible, and try to keep all your OS-specific calls in one spot.

    Check out Boost: (www.boost.org) There is a LOT of useful stuff in here, and it will certainly speed up the development process.

    Finally, make sure you design it properly! A couple of well-defined interfaces to separate things out will go a LONG way towards simplifying code, as it will ensure there is less coupling between different code modules (i.e. they don't depend on eachother as much, so you can rewrite one without affecting others). This goes for ANY language. C++ doesn't directly support interfaces, but abstract classes will do the same thing.

    As for separating modules out, you could try CORBA (as you mentioned): ORBit (orbitcpp.sourceforge.net) is a free implementation (that happens to be used by GNOME). But to be honest you probably won't need to go to this effort. If written properly, your code should be stable enough that you don't even need to separate code out into separate processes. The furthest I'd go in your situation would be to write a command-line application that does all the work, then have a graphical client (although you could write this in a different language; don't get me started on graphics library support under C++) that uses a socket or TCP/IP to communicate with the worker thread. In this case, you could just use a very simple protocol to

    --
    -- Dramatisation - May Not Have Happened
    1. Re:It's not the language that counts... by TerranFury · · Score: 1

      >Use exceptions instead of value checking, dammit! Every time you call a function that "returns 0/false/-1 on error" you are exposing yourself to possible bugs. Try to avoid this wherever possible, and try to keep all your OS-specific calls in one spot.

      I've heard this before, and I've got to admit that I don't completely understand it. Is the problem simply that a function might get called without the requisite "was-the-return-negative-one" check to follow it -- and that using exceptions helps to prevent you from making that error? Or is there another point that I'm missing (obviously, exceptions are also advantageous when any number, including -1, could be a valid return.)?

    2. Re:It's not the language that counts... by insert_username_here · · Score: 1
      I've heard this before, and I've got to admit that I don't completely understand it. Is the problem simply that a function might get called without the requisite "was-the-return-negative-one" check to follow it -- and that using exceptions helps to prevent you from making that error? Or is there another point that I'm missing (obviously, exceptions are also advantageous when any number, including -1, could be a valid return.)?

      Both... For one, it is the whole "was-the-return-negative-one" thing - since EVERY single call could return an error code, that's a lot of possible mistakes. Of course, languages (like Java) that include checked exceptions (i.e. you MUST handle all possible exceptions) also screw this up, because every function call that could throw an exception must include exception checking around it, leading to lots of "try { ... } catch (Exception ex) { }", which is just as bad or worse.

      But the other thing is the desire to make it easy to separate error detection from error handling. For example, a lowly file I/O library used by a web browser to read and decode .gif's may be aware of a .gif format error, but doesn't know how to handle it. So it needs an easy way to tell the invoking code that there's an error, so the invoking code can handle it properly (i.e. display an image broken icon). Although, this is still possible with error codes...

      --
      -- Dramatisation - May Not Have Happened
    3. Re:It's not the language that counts... by Anonymous Coward · · Score: 0

      Great comments.

      Just a quick CORBA note:
        See also ACE and omniORB, in addition to those already mentioned. They all have their ups and downs.

      Also, if you aren't married to CORBA specifically, take a look at Ice ("http://www.zeroc.com"), designed by Michi Henning and others. It has everything I love about CORBA but is more efficient and has a MUCH nicer C++ API.

  40. Try the following by Anonymous Coward · · Score: 1, Interesting

    If you really want stable programs using C++, be sure of the following basics -
    1. Hire good programmers.
    2. Make sure that EVERY function is defined with a specification, describing everything within the function. This allows you debug much easier.
    3. Make sure that you've got all requirements written.
    4. Try not to use fancy stuffs such as function pointers, de-referencing pointers, etc. Not all programmers are genius.
    5. 1 good practice, if you allocate memory in an object, make sure that the same object is responsible for de-allocating memory. This is commonly practical.
    6. For IPC, try not to use shared memory. Using message queue makes your work easier because of its guarenteed nature. Try to use MQ Series or something similar. They provides a robust mechanism for transferring and retrying data. It is the money worth spending. It is also compatible with Windows and Linux as well.
    7. Stick to ANSI C++ functions to ensure compatibility.
    8. Use a portable UI language such as qt.
    9. Test, test and test. Peer review codes.
    10. Establish a naming convention for variables and classes.

  41. must steralize biological units... by v1 · · Score: 1

    should be portable to Windows without much difficulty."

    ...

      insure that the resulting program is as crash-free as possible?

    errrror.... eeeeeeeeeror... (computer explodes)

    --
    I work for the Department of Redundancy Department.
  42. What You're Asking For Is....Difficult by OmgTEHMATRICKS · · Score: 1

    But there are ways to approach this problem. Here are a couple:

    1. Read absolutely everything you can find on Software Reliability.

    2. Experienced Software Engineers opinions should count for more than Joe Q. Random here on Slashdot.

    3. The fact that you are doing this in C++ is not the problem. More to the point, the quality of your development staff is paramount. One bad programmer set loose on a good project can wreck it.

    4. Learn and use the priciples Extreme Programming. This should take care of many of your reliability problems.

    5. Define *exactly* what you mean by "never crash". What are the risks involved? If it crashes, do people die or go to jail? If thats the case then you need to seriously consider correspondingly large funding levels, and ....

    6. Testing. Addressed somewhat by Extreme Programming. You absolutely positively need to define exhaustive tests for each module, before you even bother coding it. This means you need to encode exactly what each module should be producing for a given set of inputs and use good sense in your OO programming to isolate each object/class from side effects and cascade failure. Furthermore, test not just for inputs and outputs, but for timing and also consider security implications. What if the system doesn't normally fail unless someone is trying to push it into a failure mode (known as a morbidity state). Make sure you are do tests for input validity. Buffer overflows in your code can open the entire system up to hacking. If this is a web app, scan it with WebInspect. Hire a penetration team to do application vulnerablity testing on it. Have the platform built from a known good system image. Lock the machine down. Test the platform for vulnerablities.

    7. Test, Test, Test. Run the test suite with each and every build. Make each programmer responsible for writing the test cases against his partners code. If the test cases fail, make the responsible programmer fix the code (or the tests if they are broken) before the new module/class can be checked in.

    8. You are using a decent version control system right? Anything is better than nothing. RCS, CVS, SVN whatever.

    9. Use a proper software engineering life cycle. Make sure you never push code directly into production before Q/A testing. This can suicide a project (and a company) faster than you might imagine. If the tests are properly written, if positive tests results are required before code checkin, then Q/A should be a very fast process and they will thank you.

    go!

  43. Good call by lifeisgreat · · Score: 2, Interesting
    Good call. I'm not sure why C++ is being mandated for something that has stability as a top priority. Though there are some language-independent things that should be taken into account:

    Executive summary of this post: Keep it simple. As simple as it can be while getting the job done. The more buzzwords you think about implementing, the more you need to reconsider whether you really need that whiz-bang feature.

    You need to abstract your design into really independent layers, such that the backend processing can be done across linux, windows and even beos slaves simultaneously, and the frontend is viewable via a web interface, fed into excel or whatever. You can't look at this as one big project, but many independent (and more easily verifiable!!) applications cooperating with each other.

    My impression from the description is that you want a system like folding@home for corporate customers - they have a whole heap of data they want analyzed (parallel workload across many clients) and a small subset of results they're interested in. Don't make things any more complicated than they have to be - the data sets could simply be files that are partitioned by a master, sent out when requested to client workhorse computers, getting there by http, nfs or whatever, processed, and the results returned into an incoming directory for a simple frontend to tabulate.

    The biggest mistake you could make is having one gargantuan application in charge of everything. The race conditions will drive you mad, be they in data access, allocation, retrieval, dispatch or anything else you're trying to manage that the OS could do for you.

    Just look at Froogle. Their millions upon millions of store/price listings are fed by people ftp'ing a feed of tab-separated text values.

  44. Boehm and RAII? by tepples · · Score: 1

    How well does a Boehm garbage collector work with the Resource Acquisition Is Initialization pattern? In Boehm's library, do destructors or finalizers get called in any sort of predictable order?

  45. Know what is happening by SEWilco · · Score: 1

    I suggest you plan on knowing what is happening. Choose a logging system to use for reporting informational, debugging, and error conditions. Then use it generously. As reliability is important, you'll probably be testing input for sanity, and you should have messages available so people can figure out why data is rejected. Also have available informational messages about decisions being made, so it can be found that, umm... no widgets are being emitted because a gadget needs to be supplied.

  46. test with valgrind! by graveyhead · · Score: 4, Interesting

    valgrind -v ./myapp [args]

    It gives you massive amounts of great information about the memory usage of your program.

    The other day I spent nearly 3 hours trying to decode what was happening from walking the backtrace in gdb. Couldn't for the life of me figure out what was happening. Valgrind figured out the problem on the first run and after that, I had a solution in a few minutes.

    Highly recommended software, and installed by default on several distributions, AFAIK.

    Enjoy!

    --
    std::disclaimer<std::legalese> sig=new std::disclaimer; sig->dump(); delete sig;
  47. Erlang by Anonymous Coward · · Score: 0

    I know you asked about C++, but for fault-tolerant network applications, nothing beats Erlang.

  48. Oh come on... by wbren · · Score: 1, Flamebait
    The application is meant to primarily run on Linux, but should be portable to Windows without much difficulty.
    Well there's your problem.

    I know: -1 Flamebait. But really, this is Slashdot. A story with such a minor reference to Windows going without a Windows-bashing comment for this long is just inexcusable.
    --
    -William Brendel
    1. Re:Oh come on... by Anonymous Coward · · Score: 0

      Bugger off, dingus.

    2. Re:Oh come on... by wbren · · Score: 1

      Thanks Anonymous Coward. I'll get right on that...

      --
      -William Brendel
  49. I am invoking Greenspun's 10th law by Latent+Heat · · Score: 1
    Just as it is assumed that a language like C or C++ translates statement-by-statement into machine code, you are assuming that a language like Python translates line-by-line into C++. Does it?

    A variable in Python is a variable as in anything else, but a variable is a reference to an instance of a type that could be anything -- the referenced instance has a type as opposed to being some universal type like a string, but it can be assigned on the fly, and it can be a number, a string, an object instance, a class, or a function. I suppose assignment is just copying the reference, but as soon as you do anything with it, you have to somehow look up the dynamic type and decide to do something legal. And fail gracefully if called to do something illegal.

    And as to memory allocation, everytime you touch a reference you are doing something with a reference count, and I believe there is some kind of primitive mark-scan garbage collection layered on top of the reference count to break circular chains. Are you going to hand translate that into C++ as well?

    Greenspun's 10th law is this inside joke among Smug Lisp Weenies (TM) that any sufficiently complicated Fortran program (back in the day, today substitute C/C++ program) implements a good chunk of Common Lisp, only slower and with a lot of bugs. I may offend people to compare meek Python to mighty Common Lisp, but Python has a sufficient dynamic behavior to make the connection.

    My advice on the reliable C++ program is 1) design to the level of having a clear idea of the architecture of your app before coding -- the classes, their purpose, their containing other objects, 2) for each object where a reference is contained in another object, do some kind of code reading/verification/check of conformance to a standard you have established as to how that object gets deleted in a safe way. It could be reference counts, auto-objects, caller deletes/callee delets -- just decide on what you are going to do and read code to see that you are consistent about it.

    1. Re:I am invoking Greenspun's 10th law by blair1q · · Score: 1

      I would not replace it line-by-line.

      If the problem is decomposed properly, it can be replaced object-by-object or function-by-function, and still make sense.

      If it is not, it can still be so replaced, but there will be times it doesn't make sense (probably right from the start all the way to the end).

    2. Re:I am invoking Greenspun's 10th law by mkcmkc · · Score: 2, Insightful
      [Y]ou are assuming that a language like Python translates line-by-line into C++. Does it?

      I've been following this methodology (Python first, then C++ as/where needed) for a number of years. In all of that time, I've only had one application where I ended up needing to drop into C++ at all. In that case, a couple of pages of Python did translate into a couple of pages of C++, virtually line for line. Heavy use of STL allowed this, as there are a lot of data structures and algorithms there that map more-or-less directly to Python. The main problem was that the STL tended to be either buggy or to have razor-sharp edges upon which to cut oneself.

      Python is generally a win because (1) you can write the same working functionality much faster than in C++, and (2) the specifications for apps tend to vary wildly over time, so a high-level language lets you go with the flow.

      --
      "Not an actor, but he plays one on TV."
    3. Re:I am invoking Greenspun's 10th law by Breakfast+Pants · · Score: 1

      "Greenspun's 10th law is this inside joke among Smug Lisp Weenies (TM) that any sufficiently complicated Fortran program (back in the day, today substitute C/C++ program) implements a good chunk of Common Lisp, only slower and with a lot of bugs." You are forgetting the corollary: "even common LISP."

      --

      --

      WHO ATE MY BREAKFAST PANTS?
    4. Re:I am invoking Greenspun's 10th law by Anonymous Coward · · Score: 0

      you are assuming that a language like Python translates line-by-line into C++. Does it?

      No, but it could, at least in principle.

      A variable in Python... has a type as opposed to being some universal type like a string, but it can be assigned on the fly

      No, it doesn't. All things in Python have the same type, which in a typed language would be represented as a tagged union of an integer, a float, an array, the empty type, a pair, an error representation and probably some more primitives. This can be done in C++, too, but isn't useful all that often. A naive Python->C compiler would do this, however.

      garbage collection... Are you going to hand translate that into C++ as well?

      Probably not. A lot can be done using plain stack allocation, std::auto_ptr and boost::shared_ptr. Beyond that, there's always the Boehm-Demers-Weiser-Collector, and while some algorithms profit enormously from garbage collection, many do as well or better without.

      No, these are not the parts of Python that are magic. Its real advantage is higher order functions, anonymous functions and lexical closures. Guido is an asshat for implementing a half-baked lambda and for wanting to remove map and reduce. If you generate and evaluate code at runtime, that's also a feat that C++ cannot perform. I don't think it's useful all that often, but when it is, translation to C++ is completely useless. Anyway, it works much better in a real Lisp or Scheme.

      That said, I wouldn't use Python in the first place, for personal preference. But I would never try to translate a working Python program into C++, not for performance reasons or because of a management decision. I'd translate critical parts, after having a profile point them out to me.

  50. What a frightening post. by AltGrendel · · Score: 2, Insightful

    Sounds like the poor soul is in over his/her eyeballs.

    --
    The simple truth is that interstellar distances will not fit into the human imagination

    - Douglas Adams

  51. If you have to ask this question by GomezAdams · · Score: 1
    you might consider a career at RadioShack selling cell phones.
    However the answer to your question is: DESIGN (Requirements Doc), DESIGN (High Level Design doc and Test Plan), DESIGN (Detail Design doc). CODE. Then TEST, TEST, TEST, TEST and RETEST. After that's done. then TEST some more.
    Get customer signoff at every stage of design so as to have a stable target. Nothing screws with stability more than a customer/client who is allowed to change the requirements on the fly.
    Following this pattern I've designed and built communications servers for credit card authorizations and N-tiered communication servers for claims submissions that ran error free for five or more years. But in C and UNIX or DOS - never Winblows. Or C++. But the design,code,test 'till you puke paradigm will work all the same.

    Good Luck.

    --
    Too lazy to create a sig...
  52. Have to say this... by n54 · · Score: 1

    ...although not strictly true, it's just too good of an Ask Slashdot motto to pass up :)

    Ask Slashdot: impossible questions with impossible answers!

    Ref:
    "I need to create an ultra-stable, crash-free application in C++"
    "...due to reasons of efficiency and availability of core libraries."
    "...but should be portable to Windows without much difficulty."

    Lots of posts with interesting advice though so best of luck! Would make for an interesting Slashback entry when/if you make it succeed (and possibly even if you don't).

    --
    this additional sig includes a portrait of Mohammed in support of freedom of expression, feel free to reproduce it

    --
    this comment is provided "as is" and without any express or implied legibility or congruity [...]
    1. Re:Have to say this... by maxwell+demon · · Score: 1
      Well, I've just written an ultra-stable, crash-free, ultra-efficient program in C++. I haven't tried it under Windows, but I'd expect it to work there as well. Here's my masterpiece:
      int main() { return 0; }
      See? It's absolutely no problem! :-)
      --
      The Tao of math: The numbers you can count are not the real numbers.
  53. preconceptions or misconceptions? by abes · · Score: 1

    First of, not sure why a big deal is made that it's in c++. c++ was developed to make more stable code. Sloppy programming in any language will cause a crash. I can write python code that will come to halt, it's not that hard.

    It sounds like part of the problem is you don't *know* the c++ language. I suggest your first move is to get a book. Bjarne Stroustrup's book is pretty decent, and he goes into design issues.

    Here are a couple features that can help your code be stable:

    * Object-oriented design allows you to protect your variables by providing a protective layer. Provide access functions to change these variables. This makes debugging a cinch too, because there will be very few places you need to look that directly change variable 'foo'. Also, the constructors allow making sure that your variables are properly initialized. Humans err, so it's not perfect, but what is? You can easily come up with a system to make sure every new variable introduced will be initialized properly.

    * Templates allow you to write code once, and use many times. The less code you have, in theory the less errors you will introduce.

    * Smart pointers are you friend.

    * STL - standard template library, provides almost all the standard container classes one would ever wish for. Less coding on your part, less errors.

    * You can actually find garbage collectors for c++ (I am assuming this is why you might think other languages might be better than c++). The advantage, you don't have to worry about memory allocation. The disadvantage? You will lose some of your precious speed.

    * Expections. The biggest reason for a program crashing, besides just plainly bad code (i.e. overwriting memory locations etc.) is not handling error conditions correctly. Exceptions are a huge leap from standard C in that they allow you to manage errors in a much more sane way. It will make your code a little more ugly, but if crashing is a major concern, use them.

    * RTTI - run time type identification, yes that's right, c++ can do run time inspection if you want. You can use this to make sure that functions are receiving the correct types.

    * '#ifdef __DEBUG__ #endif's make code a little ugly but is a great way to have production and a testing code. Put code in to check the sanity of things.

    Other posters have suggested that you avoid pointer arithmetic. Generally, it's not a bad practice, but just like fire, pointers aren't bad. Sometimes you *need* fire to do certain things. No getting around it. Just remember, you are playing with fire.

    As for design, you should read books. There's a couple good ones out there. You should also read the Linux guidelines. One of the best ones:

    * Keep all your functions below 20 lines of code. I adhere strongly to this, and it has kept my code relatively bug free (although, code practices cannot save your from your own stupidity).

    In general, keep your code small, and modular. This allows you to test out portions and check the sanity of things.

    It is possible to use c++ with other languages. For example, there is a library called boost::python, which allows you to very easily create python modules.

    On a final note, I've written tons of simulation code in c++. The only time I really encountered crashing code, was when I had code that sent out data to be crunched over TCP/IP, and then receive back the results. The crashing was simply because I didn't have enough time to write all the error checking code. The more distributed or complex the design, the more errors that can arise, and you have think of what they are and be able to catch them all.

    1. Re:preconceptions or misconceptions? by Chandon+Seldon · · Score: 1

      Garbage collection and being a good C++ programmer fixes most of the issues with C++, but a higher level language adds two things:
      1.) Range checking by default. You can never access item 14 in a 8 item array in Python.
      2.) Less code. If 99% of your code is error free, that still leaves a bug in every 100 lines of code. If you can write 200 lines of C code in 50 lines of Python...

      --
      -- The act of censorship is always worse than whatever is being censored. Always.
    2. Re:preconceptions or misconceptions? by abes · · Score: 1

      Ranging checking can be added c++ with operator overloading quite easily. If I am not mistaken, I beleive that some commercial versions of the STL come with this (although you do have to pay the cost of performance).

      Less code? Less code for *what*? You need to be exact what you mean by this. If the libraries are already written, which they usually are, then you don't save anything.

      Granted, c++ tends to do less for you so you know exactly what time penalty you will pay, it's usually easy to create your own class to do exactly what you want without much code.

    3. Re:preconceptions or misconceptions? by Chandon+Seldon · · Score: 1

      If all your programmers are excellent C++ programmers then working in pure C++ is great - they'll have the understanding and dicipline to treat straight pointers, arrays, and C library functions like the landmines they are. If you assume that at least some of the team aren't overskilled ninjas, it very well may be better to do some of the work in a language where the default tool isn't a loaded foot-aimed rocket launcher.

      --
      -- The act of censorship is always worse than whatever is being censored. Always.
  54. Code generators, managers, frameworks, developers. by radtea · · Score: 1

    Heavy use of code generators is always a good place to start--the less code you write, the fewer bugs you will create.

    Distributed applications are very, very hard. It has all the joy of multi-threaded code with latency and communications issues added in. Stability of the overall system can only be achieved by a layered design: I've never seen the design patter described, but there is a "Manager Pattern" in which one process takes responsibility for controlling another process or set of processes. Autonomous restart is not a good idea because the single node that has experienced a crash does not have all the information required to make a good judgement about what to do. An external manager process that has an overview of the whole system status will do better.

    Also, restarting a process and hoping the crash does not happen again is not in general the right thing to do, as students of the Ariane V disaster will realize. In that case there were multiple redundant processors that all had the same bug (relative to the inputs they were getting from the new vehicle). In most cases restarting after a crash will just result in another crash. Realistically, you need to be able to inform the user that something bad has happened and ideally give the user the opportunity to intervene (change parameters, for example) before restarting the process. This may require that the whole data analysis run be restarted, again indicating the need for an external manager process to co-ordinate everything.

    For IPC, if you are using a common language on all platforms I strongly favour XML serialization and sockets. Any good code generator will generate serialization code to dump your classes to an XML string, and you can then send the string through a socket. It is relatively easy to do this, and avoids the huge overheads that CORBA involves (the only large project I've used CORBA on has since stripped it all out as being too heavy-weight, a decision I think is quite reasonable.)

    Using a solid framework like Qt or wxWidgets (which I've honestly found to be superior to Qt in many respects) will help reduce the amount of code you write. For crash-free code you must use open-source frameworks as much as possible, because every set of libs has bugs, and the only way you can track them down and fix them is if you have the source.

    Finally, you should think about hiring someone who's done it before :-)

    --
    Blasphemy is a human right. Blasphemophobia kills.
  55. Why stop there? by davebo · · Score: 0, Flamebait

    Here's a better request: "I want an ultra-stable, crash-free application in C++ and a pony."

    Anyone that would think it'd be a good idea to Ask Slashdot(tm) for advice on how to write the program you described isn't smart enough to write said program. Seriously. Call your boss/manager/lab supervisor/cult leader and tell them to find somebody else for the job, because you will fuck it up just as sure as the sun will rise.

    And for all of you folks suggesting this guy/gal writes it in Python/Perl/.Net/Whatever instead of C++, give it a rest. Please. Does the questioner sound like the kind of person that would bother to write exception handlers? That would even bother to buy a frickin' book already to find out what an exception was? No, they do not.

    Christ. I'm sick of this sea of idiots.

    1. Re:Why stop there? by Anonymous Coward · · Score: 0

      I couldn't have said it better myself. Too bad my unused mod points expired yesterday.

  56. What's the application? by Animats · · Score: 1
    What are you trying to do? You haven't said.

    If you really want the reliabilty you say you want, you probably need something like QNX with the High Availability Toolkit. That's what drives the newer Cisco routers. Or a Tandem system from HP. Or some kind of fault-tolerant cluster architecture.

    But you probably don't, or you would have mentioned MTBF requirements and allowed restart times.

  57. minimize your own code when possible by Ktulu_03 · · Score: 1
    A lot of already built software is available to help you:
    • The Boost library offers a number of useful tools to aid in C++ development. shared_ptr will offer a reliable reference counted pointer mechanism, that will help with eliminating memory leaks. scoped_ptr, scoped_array offer automatic memory cleanup.
    • Use STL containers, instead of home-grown linked lists, maps, etc. Get to know which container is the right one to use, under the circumstances.
    • Use STL algorithms. When using STL containers, use the STL algorithms to perform actions on the containers. The built-in loop mechanisms know how to enumerate through a container in a more efficient way than writing your own loop.
    • Combine the use of shared_ptr and STL containers, to store pointers in a list (for efficiency), but be able to have them automatically deleted when removed from the list.

    If you have to write multithreaded code, plan out the design before implenting it, and always put the locks in as part of the design, not trying to shoehorn them in.

  58. Forget it. by Pig+Hogger · · Score: 4, Funny
    Forget it, with C and C++.

    Those are low-level programming-jock languages disguised as high-level languages. As long as the punks who program them will have pissing contests in code obfuscation, you can count on having buffer overflows and memory leaks.

    1. Re:Forget it. by yamla · · Score: 2, Interesting

      There's no excuse for buffer overflows and memory leaks in C++, not with TR1's smart pointers and not with the standard library's containers. That's not even considering garbage collectors which have been available in C++ for years.

      --

      Oceania has always been at war with Eastasia.
    2. Re:Forget it. by Anonymous Coward · · Score: 0
      Forget it, with C and C++.

      And I suppose your own 'language of choice' has a compiler/interpreter not written in C/C++ ?? Choose any current day compiler and I bet you will find that it is both written in C/C++ and it runs on a Operating System written in C/C++. Of course there would also be some assembler in there to optimize it too, so to say that you should give up on something that you also rely on daily.

  59. Unit Testing and Smart Pointers by pjkundert · · Score: 4, Insightful
    60,000+ lines of communications protocol and remote industrial control and telemetry code. No memory leaks, and less than 5 defects installed into production.

    The reasons? A unit test suite that implements several million test cases (mostly pseudo-random probes -- the actual test code is about 1/3 the size of the functional code). In fact, the "defects" that hit production were more "oversights"; stuff that didn't get accounted for and hence didn't get implemented.

    Just as importantly; every dynamically allocated object just got assigned to a "smart pointer" (see Boost's boost::shared_ptr implementation).

    Quite frankly, compared to any Java implementation I've seen, I can't say that "Garbage Collection" would give me anything I didn't get from smart pointers -- and I had sub-millisecond determinism, and objects that destructed precisely when the last reference to them was discarded. The only drawback: loops of self-referencing objects, which are very simple to avoid, and dead trivial if you use Boost's Weak Pointer implementation.

    We didn't have access to Boost (which I Highly Recommend using, instead of our reference counted pointer) when we first started the project, so we implemented our own Smart Pointers and Unit Testing frameworks.

    I've since worked on "Traditional" C++ applications, and it is literally "night and day" different; trying to do raw dynamic memory allocation without reference counting smart pointers is just insane (for anything beyond the most trivial algorithm). And developing with Unit Testing feels like being beaten with a bat, with a sack tied around your head...

    --
    -- -pjk Perry Kundert perry@kundert.ca http://kundert.2y.net
    1. Re:Unit Testing and Smart Pointers by pjkundert · · Score: 1
      Sorry; that's "developing without Unit Testing feels like being beaten with a bat, with a sack tied around your head..."

      (Freudian slip? Nah... ;)

      --
      -- -pjk Perry Kundert perry@kundert.ca http://kundert.2y.net
    2. Re:Unit Testing and Smart Pointers by Brandybuck · · Score: 1

      trying to do raw dynamic memory allocation without reference counting smart pointers is just insane

      It really depends on how you use your objects. There really is no need for a smart pointer as a private data member, for example, if you only allocate it in the constructor and only free it in the destructor.

      --
      Don't blame me, I didn't vote for either of them!
    3. Re:Unit Testing and Smart Pointers by cpeterso · · Score: 1


      Sorry; that's "developing without Unit Testing feels like being beaten with a bat, with a sack tied around your head..."


      ok, that makes MUCH more sense! I had to read the last paragraph of your orignal post about 4 times to figure out what you meant. My conclusion was that you meant "without" or that you meant Unit Testing using "traditional C++" was painful. :)

    4. Re:Unit Testing and Smart Pointers by Anonymous Coward · · Score: 0

      In most cases, yeah, that's a fine way to do it. However, you have to watch out for the possibility that the constructor could throw an exception after you've allocated the memory, in which case the destructor is never called and the memory never free()'d. It's a case that comes up more often that you might think. A boost::shared_ptr sets it right easily, and incidentally in compiled release code is no different than a regular pointer--so you'd might as well.

    5. Re:Unit Testing and Smart Pointers by tgv · · Score: 1
      trying to do raw dynamic memory allocation without reference counting smart pointers is just insane

      Well, relying on reference counting is just as insane: one cycle and you're memory can fill up pretty quickly, potentially crashing your application.

    6. Re:Unit Testing and Smart Pointers by Anonymous Coward · · Score: 0

      yup, memory leaks and buffer overruns are pretty much a solved problem in C++ with a bunch of good practices and libraries (like boost).

      they're a solved problem in other languages with GC and some kind of runtime management.

      yet people still have this fear and loathing, wandering around screaming "If I use C++ my app will crash, but if I use java it'll be slow", like a bunch of Muslims who've just seen a joke for the first time.

  60. Oh, come on now... by Max+Threshold · · Score: 1

    Linux never crashes unless you try to upgrade something. :o)

  61. Simple by Pao|o · · Score: 1

    Don't use Windows. :)

  62. Resources / Techniques by dennisne · · Score: 1

    First, you want to get some very experienced engineers who have done this type of thing before. Try ones with a background in either Avionics or medical devices, since both are life-critical / mission critical arenas. Second, you may want to look at companies which make fail-safe systems as these usually require special purpose hardware. HP has a computer line called NonStop which may be worth looking into (no, I don't own any HP stock :)). In terms of techniques: 1. NEVER, NEVER, NEVER, NEVER -- NEVER execute a loop waiting for some event to happen, that does not have a bailout mechanism, even if its just counting a variable up to (or down from) a few million or so (however long you've determined would be the maximum wait interval. If a piece of hardware breaks or a sibling thread crashes you'll be out to lunch. 2. Try to use a real-time system that is used on fail-safe systems commercially. 3. Don't use Windows. No matter how defect-free / error-free you make your system, it won't matter, because Windows will have more than enough defects and flaws to make your system fail in weird and mysterious ways. 4. Use a journalling file system like ext3 or reiserfs. 5. keep a recent copy of your operational state / data somewhere safe, like in non-volatile memory. If your system has to restart itself, this data will help you become operational again much faster. 6. Use a watchdog timer. Basically, this is a piece of hardware that your code has to "feed" on a periodic, repeated basis. If your code gets hung up in an infinite loop somewhere, the watchdog timer will assert the reset line and start things up again. That's where your "warm" data comes into play. 7. As many here have mentioned, try to partition your system in such a way that you can stay away from C++ as much as possible. 8. As some here have mentioned, real-time java or a commercial garbage collector library service could help alot in avoiding pesky memory leaks. 9. Assume you will mess up the first time. Its a much more realistic assumption than assuming you'll get it right the first time. Hey, most of us didn't even get our first KISS right the first time, and what you are looking at is alot more complicated than that :)). So, schedule enough time to do so (call the first one an R&D program), collect enough information about your design decisions and rationale that they will help you to understand where you went wrong, and help you to do better the second time around. Good Luck. 10. You've gotten alot of good comments from a lot of very intelligent and experienced people on this list. Read them over carefully. Good Luck dennis

  63. Congratulations! Nice Work! by aendeuryu · · Score: 5, Funny

    "I need to create an ultra-stable, crash-free application in C++. Sadly, the programming language cannot be changed...

    From zero to flame war in under 20 words. Well done!

    1. Re:Congratulations! Nice Work! by OOGG_THE_CAVEMAN · · Score: 1

      Yes, and you can tell that very few readers got far enough to get the

      The application is meant to primarily run on Linux, but should be portable to Windows without much difficulty.

  64. Be realistic by The+Clockwork+Troll · · Score: 1
    Do your best to code correctly, write ample unit and integration tests for each component.

    But at the end of the day, you have to assume your program is going to crash, either because of intrinsic uncaught bugs, or more likely, unexpected system problems (power outages, network wires accidentally unplugged, etc.).

    What to do? Concentrate as much on recovery mechanisms as you do on code correctness, in case your program (or an entire node) does crash.

    This has less to do with C++ (or any language) and more to do with thinking through how to journal your program's state (perhaps you are running on top of a file system or database that has transactional semantics and can help you here) and how to have the nodes coordinate after a failure.

    --

    There are no karma whores, only moderation johns
  65. Well... by blair1q · · Score: 1


    I could tell you, but then I'd have to bill you.

  66. Stable program will crash someday... by zeekiorage · · Score: 1

    I don't know how to make a program crash free. What I do know is - if you have enough logging in your application, when your program does crash, you can quickly look at the logs and find the exact class/method that cause the fault and fix it.

    Break down the big project into small components. Have your programmers write unit test for each components and also add instrumentation/logging code, with an option to turn on/off the logging.

    Many people are suggesting that you move to the managed language, even when the OP has stated that it is not really an option. I think moving to managed language can help with stability but it can't eliminate all the crahses or memory leakes. You can still have things like null pointer exceptions or an ever growing array hogging lots of memory.

  67. Engineering, the art of compromise and tradeoffs by Morgaine · · Score: 1

    >> As it is, though, your stated goals really don't seem to add up.

    I agree entirely with your reply here. The poster's statement (below) is frankly ludicrous:

    >> Sadly, the programming language cannot be changed due to reasons of efficiency and availability of core libraries.

    Well in that case, sadly, the inherent unreliability of the programming language and core libraries cannot be changed either. Efficiency is the *primary* inverse determinant of reliability.

    This is ENGINEERING we're talking about here, ie. a practical discipline that's all about making tradeoffs in one area in order to reap benefits in another. He's not willing to make any key tradeoffs, so he's not going to gain what benefits he seeks either.

    --
    "The question of whether machines can think is no more interesting than [] whether submarines can swim" - Dijkstra
  68. Asserts() are your best friend. by Anonymous Coward · · Score: 0

    Assert every input parameter. Assert every returned value. Shred your garbage (set pointers=null after deleting them). Take a stick to programmers who use #if's. Take a bat to programmers who use templates. Have unit tests for every public method. Have stress tests that check for memory leaks.

    1. Re:Asserts() are your best friend. by Duhavid · · Score: 1
      Assert every input parameter. Assert every returned value.


      only helps during the debugging. s/Assert/Check/g

      Shred your garbage (set pointers=null after deleting them).


      absolutely.

      Take a stick to programmers who use #if's.

      Take a bat to programmers who use templates.


      Code review and educate programmers about misuse, where misused.
      Dont throw something out automatically, if properly used.

      Have unit tests for every public method.

      Have stress tests that check for memory leaks.


      Absolutely. Automate the running of those
      tests to the extent possible.
      --
      emt 377 emt 4
  69. Suggestions by gte910h · · Score: 1

    1. Write a coding specification that specifies what portions of C++ that are usable on the project.
    2. Read Code Complete 2
    3. Only use Autopointers. No real pointers. Not for anything.
    4. Spec the program out down to the routine level. Have this working before you write any code.
    5. Code reviews, code reviews, code reviews.
    6. Read the section in Effective C++ on interface/model separation. It will help you make each section of your code losely coupled enough that you have a chance to make your self-restarting idea work.
    7. While you think you're going to be able to write this on windows, I think if you're going to try your "making sure nothing's dead for too long" scheme, you should look at Hard Real time linux to put under a linux installation, THEN port the program to windows if they demand it. Either that or make a hard real time linux monitor for the entire system to make sure the system is going.
    8. Make this system LEAN LEAN LEAN. Cut out every feature imaginable. Develop the baseline system and a fully featured one. Have metrics on how every features changes the baseline so you can pull back in and out things

    --
    Want to see every step I took to start my company? http://www.rowdylabs.com/blogs/pitchtothegods
  70. eschew electrons by Anonymous Coward · · Score: 0

    Electronic components are far too fickle for anything that must be ultra reliable. For such applications, you must build a Babbage analytical engine out of titanium, like we do here at .. oh, unexpected visitors .. I have to g............

  71. I'm In A Similar Situation by eric2hill · · Score: 1

    I started writing an application in C++ a few months ago. I have similar goals, specifically stability and data integrity. Obviously the language doesn't really help with those two goals, but a strong flexible design combined with a large test-case framework is a good place to start.

    As for the middleware, I've been looking at the Ice middleware library from ZeroC. It can be commercially licensed for closed-source development, or used freely in an open-source project.

    From the documentation, their protocol looks like it's very well designed, and very full-featured. I also like their grid, proxy, and batch capabilities. All in all, Ice looks much better than CORBA and far easier than trying to roll my own middleware.

    Does anyone reading Slashdot have any hands-on experience with Ice? I'd appreciate any comments/advice/email you care to share on this topic.

    --
    LOAD "SIG",8,1
    LOADING...
    READY.
    RUN
  72. Recent /. Story by aztektum · · Score: 1

    Maybe you can find some jewels of wisdom about stable code in general from this story

    --
    :: aztek ::
    No sig for you!!
  73. Pragmatic Programmer by Anonymous Coward · · Score: 0

    Read it and follow it. Beyond that, expect errors while testing and don't be discouraged by them. Don't be afraid to start completely over. The best way to get an error free system is to make all the errors in versions 1,2, and 3, then put version 4 into production.

    v1: Code prototype (after designing of course). When you find an error in design, make a cludgey work-around. Finish entire prototype. TEST TEST TEST

    v2: Re-design while keeping in mind all the errors you ran into, design them out. Code prototype and make a work-around for any new errors you find. TEST TEST TEST

    v3: Re-design while keeping in mind all errors you ran into in v2, design them out. Code program and make a work-around for any new errors you find. TEST TEST TEST

    v4: Re-design while keeping in mind all errors you ran into in v3, design them out. Code program and you shouldn't have any errors BUT TEST TEST TEST. If you do find errors, fix them elegantly. If cludge is required for any fix, redo v4.

  74. Yeah, c++ hasn't been successfully used before... by composer777 · · Score: 1, Flamebait

    Use your brain. C++ is a very commonly used language. If you can't write an application that is stable, consider another career. The only people I know who criticize a widely used language like c++ are posers and hacks. Think about it, the linux kernel is written in an even lower level language (C), and it's fairly stable. Sorry for the harshness, but I have the displeasure of working with a guy (like you), that complains about having to do serious design, and prefers to write in PERL, becuasue it's easy to use. Designing fast, scalable, stable programs is part of our profession. Either get with the program, or get out. Sorry if I didn't answer your question, but I don't consider it honest.

  75. some design patterns to consider by DeveloperAdvantage · · Score: 1

    I do think there is potential in the overall design you are choosing, with a focus on expecting stuff to break and then simply making the system robust enough that if one module fails it is either restarted or another duplicate takes over and processing still continues.

    If you go with restarting, and performance is critical, one of the important aspects will be to help you restart a downed module efficiently. From the GoF, the Memento pattern for storing an object's state may help you. The Command pattern may also be of benefit. For example, if processing something fails, you may only want to retry a certain number of times, in case there is a systematic reason for the failure. This type of functionality can be easily implemented using the Command pattern.

    Also, although I have not read it myself, you may get some good ideas out of "Pattern-Oriented Software Architecture, Volume 2, Patterns for Concurrent and Networked Objects". I read the first volume of this series and found it to be a great reference.

    My comments are focussed on the "Design Patterns" part of your question. What references have others found useful specifically for building robust software?

    I have all too often seen these supposedly robust custom written systems degenerate into a big pile of sh*t which then requires much work to get fixed up. I would strongly recommend keeping close track on the status and quality of your project, and, at the first sign of slippage, particularly if you hear people saying "stuff just doesn't work", get some serious professional help if you want the project to succeed.

    Good luck and I hope your project turns out well.

    --
    FREE - Java, J2EE and Ajax Audiobooks for Software Developers - www.DeveloperAdvantage.com
  76. Test, test, and test again by rattigan · · Score: 1

    Create comprehensive unit tests, and create an integration test harness as you create the product. Not only will this enforce decoupled design, it will ensure continuous confidence in the quality and robustness of your product. Doesn't matter what language you use, as long as you test, test, and test again.

  77. test it, darn it. by davygrvy · · Score: 1

    Want stability? Test it and keep testing it. Create a LARGE test suite. Per class testing, then per module, then whole app. Test 'till you're blue, then test it some more.

    --
    -=[ place .sig here ]=-
  78. Not a Python programmer, but... by SilverJets · · Score: 1

    Good God didn't you just make the program take twice as long to create? You write it in Python, debug, test, debug, test and get it working. Then replace the Python with C++ code which you then have to test and debug (at least once). If you can model it in Python in the first place, why not just start with C++?

    1. Re:Not a Python programmer, but... by Anonymous Coward · · Score: 0

      You can't be serious... because writing Python is a lot faster than writing C++, even if you have the imaginary perfect-model-documentation-that-never-changes-on- implementation.

    2. Re:Not a Python programmer, but... by SilverJets · · Score: 1

      Well if you know what you were doing in C++ I see no reason to write the entire thing in Python then rewrite it C++. If you are rusty in C++, why not take all that time you are spending working in Python first and spend it developing skills in C++? That way you don't need the "model it first in Python" step. Or if it works in Python and you are happy with it why not just leave it in Python?

    3. Re:Not a Python programmer, but... by jma05 · · Score: 1

      None of us write our software (decent sized ones, that is) right the first time. Python is more agile than C++. Once the code structure is evident it is very easy to write it in any other language. I take less time to write some code in Python and later convert it to Java than do it from the scratch in Java, especially when the requirements are not all clear and not much can be done about it. Of course, you don't need to replace everything. Just the performance critical portions if at all when using C++ (or just jython in case of Java).

    4. Re:Not a Python programmer, but... by Anonymous Coward · · Score: 0

      Learning Python takes an afternoon. Learning C++ takes 7 years, and then you realize how much it sucks...

    5. Re:Not a Python programmer, but... by GenSec · · Score: 1

      The answer just might be in the subject. My experience with Python so far has been that it is much easier to express even complex algorithms in it than in C++ or Java. My day job is a lot of C++ and some Java, but when I need to write a test tool, I usually do it in Python, because what takes an hour to do in Python would take two days in Java. And I have far less experience with Python than with the other two.

      I'll tell you a story about getting the design right:

      Last year I got interested in the Sudoku puzzles (duh!). I thought I could try writing a program to solve them. Against my experience, I decided to write it in Java. "Python's too slow and explicit types will help me with the design," I thought. Then I spent weeks banging on the code until I got something that was able to solve puzzles up to medium difficulty level, but no further - it would just go on forever.

      Finally I got fed up and thought, "What the heck, maybe Python was not such a bad an idea." Three days later I got a complete solver that so far was able to crack all puzzles I tried with it. Only the hardest require any noticeable computation time.

      Now, if what many Python programmers say is true, writing the application in Python and then rewriting just the bottlenecks in C or C++ is a good idea.

    6. Re:Not a Python programmer, but... by jellomizer · · Score: 1

      It depends on the complexity of the application.
      If you are using a complex algorithm. Python will make it much faster to develop because you can first focus on getting the algorithm working correctly. Without have to worry as much about things like type casting, memory allocation, pointers, overflow... So say you are crunching some numbers and you find a number in it gets really big very fast. In C++ you may think there is a problem with the algorithm because you are getting a negative answer, while you just overflowed an operator and it went negative on you to follow twos complement. While python will switch to large numbers (at a performance hit) but then you will get the right value but perhaps with an L at the end letting you know a value went bigger then expected so you can adjust that. Vs going back from start finding what can possibly be wrong with your code and how the hell it became negative.

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    7. Re:Not a Python programmer, but... by mkcmkc · · Score: 1
      Good God didn't you just make the program take twice as long to create?

      No, because most of the work involved in writing the Python version is design work and problem solving that you'd have to do in any case. Plus, the Python version usually only takes 10-25% as long to write. Try it, you'll like it!

      --
      "Not an actor, but he plays one on TV."
    8. Re:Not a Python programmer, but... by oever · · Score: 1

      Your story demonstrates that it is sometimes good to start from scratch, not that it's easier to develop in Python.

      By the way I cannot judge Python here, because I've little experience with it. Personally I find that writing Java with eclipse is very easy. Rewriting is also simplified a lot by the refactor functions.

      Maybe there's an equally nice development enviroment for Python, but I don't think so. Deciding on which language is best is also determined by the development environment you are using.

      --
      DNA is the ultimate spaghetti code.
    9. Re:Not a Python programmer, but... by SilverJets · · Score: 1

      Wow, Python must be such a powerful language, it takes an afternoon to learn it.

      I'd rather take 7 years to learn C++, than spend an afternoon to a language that has been dumbed down.

    10. Re:Not a Python programmer, but... by jallen02 · · Score: 1

      You have not illustrated that Python is any different/better than Java for that particular problem. Your breakthrough sounds like an algorithmic break through to me, not language driven.
       
      Often I get a flash of insight by attacking the problem from different directions (possibly languages). Perhaps some programming paradigms allow you to more naturally express certain problems, but in general most people tend to do OO or procedural Python so I don't see how Python would give you any huge advantage by just using a different language.
       
      Good algorithm design can be expressed in a language neutral format and then implemented in any language.
       
      There might be some arguments you can make for being able to better comprehend the Python code due to there being less lines of code so you are able to see more of the problem at once. This is often what helps lead me to solving bigger picture problems. This is also accomplished, for me, by refactoring bigger pieces of code into smaller objects/modules so that the core routines of the program are nothing more than skeletons to the methods doing all of the work.
       
      So, in my mind to make a good puzzle solver you need the core algorithm in an easy to understand format. Then the language you use is just a formality. (Unless you are using functional programming or some other more esoteric paradigm that is difficult to emulate in a language like C/C++/Java)
       
      Jeremy

  79. Don't by AaronLawrence · · Score: 1

    If you don't have enough knowledge to know how to approach this now (it's obvious you don't) then you are bound to not get it right for several iterations. Writing reliable software is going to take a lot of experience so you really get your head around how thorough you need to be.

    Can your task afford to have a very long period of non-productivity while you play around with ideas and learn the rather hard lessons of writing high-reliability software?

    Ideas that spring to mind:

    - NASA and their shuttle software. They have enormous resources and get it right by being very careful and formal. Go read about it. Starting point:
    http://www.fastcompany.com/online/06/writestuff.ht ml

    - Formal methods. Proving your design. Or at least formal coding/testing of the interfaces.

    - Aerospace software. Like the fly-by-wire systems. They have less resources than the shuttle and make occasional mistakes.

    Also, I would reexamine your requirements. Is it medical? Do people's lives depend on it? If not, it seems like someone is overstating the need for reliability.

    Finally, I have had some small experience with people attempting to "add" reliability to a system - like automatic restarting of modules. The usual result is to make the system MORE complex, and LESS reliable, or prone to fail in more severe ways, because simple ideas don't have the effect you'd think.

    --
    For every expert, there is an equal and opposite expert. - Arthur C. Clarke
  80. no! by pete23 · · Score: 1

    don't split things up and string them on an untested distributed "restart" architecture. this will fuck you over and be a constant source of pain.

    get the core code right through testing, purify, using safe libraries where possible, ensuring that data meets constraints before commits, etc. i don't think C++ is noticably more error-prone than any other language (although memory alloc is harder without GC, it's still a solved problem - smart pointer abstractions to obviate problems, purify to catch things you miss... etc).

  81. Some Tips by InodoroPereyra · · Score: 1
    • Write unit tests. Make a policy to include one test for each new function/method introduced to the base code.
    • Run Valgrind tests on the unit tests periodically.
    • Use Smart Pointers, maybe from Boost. Do not allocate new naked (regular) pointers in the heap.
    • Re-use code. Re-factor as much as possible. Do not allow for large, obscure, zillion-line functions.
    • Use well known, well debugged libraries such as the stlport (for STL) as much as possible. Maybe Qt.
    • Be const-correct. Pass const-references as much as possible.
    • Make simplicity and readibility of the code a strong requirement. Good code should look damn clean.
    • Don't ask in ./, we are a bunch of asses after all ;-)
  82. Software engineering, not design patterns by StrayLight · · Score: 1

    Lots of people will try to work around your requirement for C++, but I'll assume your reasons are solid and let it stand.

    What your are looking for are not design patters but software engineering practices. Specifically, you're interested in what would be called critical systems (think things like air-traffic control where failures can cost lives). These sorts of systems exist, and are written in all sorts of languages, but writing them is not a small undertaking. To get an idea of what you're undertaking, have a look at how reliability (RELY) affects things in the COCOMO II model.

    http://sunset.usc.edu/research/COCOMOII/expert_coc omo/drivers.html

    The next step is to look at some of the literature. I'd suggest starting with Somerville's 'Software Engineering', where you'll find part 4 dedicated to critical systems and part 5 dedicated to verification and validation. The chapter on critical systems validation is probably the meat of what you need, but the rest is likely needed for a solid background. Suffice to say that those saying 'test driven development' are on the way to enlightenment, but are missing a large part of the story.

    http://www.amazon.com/gp/product/0321210263/102-91 00997-2271304

    Best of luck though. It sounds like you'll be in for an interesting project.

    1. Re:Software engineering, not design patterns by Mafurio · · Score: 1

      Definitely, only I'd also recommend reading some books by Grady Booch such as:
      http://www.amazon.com/gp/product/0805306080/sr=1-2 4/qid=1139120509/ref=sr_1_24/103-2402481-4199058?_ encoding=UTF8
      also, I'd recommend programming in ADA in your free time if you have any, to get into the good habits it promotes... Although, that's a personal preference/bias I suppose.

  83. Re:Yeah, c++ hasn't been successfully used before. by Anonymous Coward · · Score: 0

    "becuasue"
    Look, development of a large (esp. disturbed) app can pose many unexpected problems,
    I suggest if you cannot comprehend the task at hand (even as vague as it was posted)
    then maybe you should refrain from posting or better yet, "consider another career".

  84. Quit crying about your tools. Craft good code. by CFD339 · · Score: 1

    Look, writing in managed code may be great for YOUR code's stability -- but only because you're writing less of it and trusting more and more to other people. In all candor, we're talking about either the JVM or the CLR (which are nearly the same thing in many respects).

    Sure, you write less lines so you write less bugs. Big deal. If you take your time and treat your work as a CRAFT and yourself as a CRAFTSMAN, you'll write good code in nearly any language.

    Personally, If I were after "Ultra Stability" (a made up phrase, by the way, with no real definition) I'd be looking first at the hardware and operating system and pulling out absolutely everything it does not need, then moving to the custom software and pairing everything down to its absolute purest, most minimal set of features and functions.

    Think in terms of simplifying the environment, the platform, and then your code. Its the external factors that are going to kill you. Get rid of as many as you can.

    --
    The problem with quotes on the internet, is that nobody bothers to check their veracity. -- Abraham Lincoln
  85. You can use C++ libraries from OCaml by Anonymous Coward · · Score: 0

    You may want to check out OCaml. You can use C++ libraries from it using something like SWIG (and the libraries of other languages too, using something like Pycaml for Python, and there's an interface for Perl too).

    Here's a nice comparisong of a ray tracer written in C++ and one written in Ocaml.

    And here are many more comparisons and information on why OCaml is so great. :)

    Oh, by the way, OCaml is much safer than C++, infinitely more elegant, faster to develop in and more readable.

  86. Re:Yeah, c++ hasn't been successfully used before. by Anonymous Coward · · Score: 0

    "disturbed"

    If you're going to point out spelling errors, it's generally best to avoid making any of your own...

  87. Use lisp for a novel approach! by Nicolay77 · · Score: 1

    First, if you need multiplatform, then code for that from the start. That kind of stuff can't be done in the end of the project. Your best shot is to use the wxWidgets C++ library.

    Then, some things in C++ are boring and prone to errors. So learn lisp and make C++ generators in lisp. I did it to develop some C++ core data structures and their corresponding persistent object storage mechanism.

    And the payback is great!

    Most errors come from refactoring, where you change one thing in one place, but forgot to change the same thing in the miriad places that should be updated. With lisp, you just change a line in your code, tell lisp to recreate your C++ files and you can be sure everything works right.

    You can test and change stuff faster with this approach. Hey, I can give you my lisp files if you want to try.

    HTH, YMMV.

    --
    We are Turing O-Machines. The Oracle is out there.
    1. Re:Use lisp for a novel approach! by Sirp · · Score: 1

      I really think that if you want to write a very stable application, using a 'novel' approach is not a good idea. Rather, use a tried and tested approach.

      That's not to say Lisp can't be used to write stable applications. If you're familiar with Lisp, and you want to write a very stable application, then it's a good choice. If someone doesn't know Lisp, then using it to write a very stable application is probably a very bad idea.

    2. Re:Use lisp for a novel approach! by ari_j · · Score: 1

      Better yet - write it in Lisp.

    3. Re:Use lisp for a novel approach! by synthespian · · Score: 1

      Write in Eiffel and achieve safety with gcc performance.

      --
      Main difference between the BSD license and the GPL license: one is from California and the other is from Massachusetts
    4. Re:Use lisp for a novel approach! by Nicolay77 · · Score: 1

      The code produced is C++, which can be audited way easier than lisp and I have lots of experience in.

      The end result is: I was able to code it faster and more reliable than if I had wrote the C++ by hand.

      However, not everything was done with the lisp->C++ code, just the boring, repetitive parts. The rest was common C++.

      Just because no one did it before this way doesn't mean it's not a good idea. The benefits were so good I would do it again a hundred times.

      In fact, I wish I used a lisp->C++ generator for more sections of the program, once the repetitive parts were obvious.

      --
      We are Turing O-Machines. The Oracle is out there.
  88. References, const like hell, bounds check... by 123abc · · Score: 1

    1) Pass references into functions/methods as much as possible (since they can't be null... in theory) There is very little need to pass pointers into methods _if_ you take the time to think about things.

    2) Properly using const will help a lot.

    3) At the cost of speed, bounds check all operator [] overloads. Use pure arrays as little as possible.

    4) Don't use loops that don't have a determined stop/abort condition.

    5) Check and handle all return codes from standard library calls or other function/method calls for that matter.

    6) You could put a global try/catch block around everthing for good measure, but there isn't much difference between this and just bombing unless you can actually handle the global error condition and somehow recover.

    7) Don't throw from a destructor.

    8) Actually use destructors.

    9) The list goes on and on...

  89. Rock Solid C++ by ovit · · Score: 1

    Tackle this with a bottom up approach.

    Try not to use the heap. Try not to use pointers.

    If you have to use the heap use a rock solid smart pointer implementation.

    Do you have to use C++? Could you just use C?

          td

    1. Re:Rock Solid C++ by Anonymous Coward · · Score: 0

      That is the dumbest post I've seen in this whole thread.

      Don't use the heap? Try not to use pointers? If he's hell-bent on using C++, there's no way to get around that.

      And how the fuck is it easier or better, in terms of pointers and whatnot, to use C rather than C++?

  90. Agreed. and a few more thoughts. by jd · · Score: 4, Insightful
    • Where they exist, use fault-tolerent components for interconnects. Making things fault-tolerent is tough, so re-using such stuff will simplify the task. Best of all, use stuff with a significant history behind it, because communication will be the biggest headache and bugs there will be hard to pinpoint exactly.
    • When coding, assume that anything can crash. I don't care if you use exception handling, reactive methods or a purple pizza, but you want components to be able to recover from failure (by restarting if need be) and you want anything that talks to it (and the data!) to be able to survive a loss of connection and handle the condition in a predictable way. (This may mean resending to another node, waiting for the old one to reset, buying said pizza over the Internet, whatever.)
    • Keep It Simple! The more layers, the greater the liklihood of bugs. (There are exceptions - if you're using CORBA, then the ACE ORB is heavyweight but generally considered pretty solid. That's partly because it has a decent amount of maintenance and has been around a while. I would probably not go for lesser-known ORBs, though.) The more complexity you can avoid, the more certainty you can have that the code is solid.
    • Analyze, Specify, Design, Implement, Validate. There are no "perfect" techniques to Software Engineering, but a few things generally hold up fairly well. The first of these is to keep the steps in the process as clean and methodical as practical. There will be some overlap, but in general you can't implement good code until you know what good code you want implemented.
    • Testing Is Important. There are more schools of thought on testing than there are programmers. (At last count, at least three times as many.) Even if nobody is quite sure what role testing has, most seem fairly convinced it has got a role. One popular creed states that design should be from the top down and testing from the bottom up. (ie: test at the level of the components that call nothing else, then build up step by step.) Another states that since you have a specification (you do, don't you? :), you can write the tests according to the specification first, then write the code to comply with the tests. You can even follow both approaches, if it helps you feel better. Just pick something and stick to it. My preferred testing method is to check "typical" conditions, boundary (extreme) conditions and erronious conditions.
    • Never assume that some other coder's assumptions about the compiler's assumptions of what was assumed by someone else entirely bears any resemblance to what you think. Computers know all about luck and hope and how to utterly crush them when you're not looking.

    Yes, some of those do conflict. How to keep things simple AND have fault-tolerence, for example. That's where a good design comes in handy, because you can get a better feel for where you should make the trade-off between certainty of working, certainty of working later on and getting some sleep this side of 2008. It's all a matter of weighing the options and investing time in the place most likely to benefit.

    (Because everything is a trade-off, anything listed above may not apply. But then, it may not need to. If you've tested a component thoroughly along all boundaries, a good sample of valid conditions and a good sample of erronious conditions, AND everything has been kept as simple as possible so that really wierd cases are unlikely to crop up, then you may decide you can simplify or eliminate fault-tolerent components. There is no point in catching errors that won't occur. In fact, that adds complexity and violates the Keep It Simple rule.)

    Oh, and as this is a networked system, testing should include testing network I/O. Use packet generators if necessary, to see how the system handles erronious packets or massive packet floods. You don't want "perfect" responses (unless you can define what "perfect" means), you want reliable responses. If X occur

    --
    It's a small world and it smells funny; I'd buy another if it wasn't for the money; Take back what I paid (SoM)
  91. Stable programming... by TemporalBeing · · Score: 1

    Stable programming can be achieved, and achieved quite well. No single method is the "silver bullet", so to say, but using a VM'd languaged or garbage collected language won't do you any good either. Here's some basic principle for any language that can help make you programs stable.

    1. Never trust anything coming in. Always check every parameter to a function and make sure that each is within the expected value ranges. For pointers, you can't tell whether they point to the right place, but you can make sure they are valid. If something doesn't look right, then return an error code - don't continue. Also check everything returned by any function you call - check for the error codes, and actually handle them; if a caller needs to handle it, then return a consistent error code and let it handle it. But, most importantly, HANDLE the errors.

    2. HANDLE all the errors from any function or procedure - whether hardware or software. Throwing an "exception" is a bad method to handling the error and really does nothing for the actual problem - it's too generic, and too easily turned into giving the error to a higher level, which just prohibits the higher level from being able to actually overcome the error (fix it, handle it, etc.). Handle everything, and do so meaningfully, and when an error occurs, clean up anything that needs to be cleaned up before returning to the caller or exiting/terminating.

    3. NEVER ASSERT!!!! Asserts will only lead to faulty, crashing programs. HANDLE THE ERRORS! (See #1 & #2)

    4. Don't trust that system calls succeed - always check that memory is allocated, clear it, and then use it; and check that the correct amount of data got written out to disk or read in.

    5. Be explicit about everything in your code. Don't assume that an "int" is signed - declare it as a "signed int"; this will help with reading and understanding the code as well.

    6. Be explicit in your logic - use an explicit structure with single-entry-single-exit principles to do the above.

    7. Since you're using C++, use Object's to control your resources efficiently. For example, don't just allocate buffers using "new" - create an entity in the program that is to do so, and then use it to do it. Return the buffer to it when you're done, and let it also destroy them. Same goes for threads, and any other resource. Don't rely on the OS, a VM, or a GC to clean up after you. DO IT YOURSELF!

    8. Reuse proven code as much as possible, and use efficient algorithms. Sometimes an STL Vector class may be good for you; othertimes it won't be. Be aware of what you're using - its benefits AND costs, and consider them all in the process.

    9. Be able to create and destroy, load and unload any object in the system - e.g. libraries. Make sure you can unload a library to re-initialize it if you need to. It would be great to be able to do this even for standard objects, but this must apply especially to libraries - first AND third party - so that you can clean out their errors or reset them if needed.

    10. Design and Architect the software to achieve its goals and requirements. After each design and architecture is proposed, revisit the requirements and (a) check that the design meets the requirements, and (b) see what other requirements are then inferred by the design and architecture. Repeat as needed until a version that can be extended is viable. Do not try to do it all in one version.

    11. Document. Document. Document. Document your code. Document your design. Document your algorithms. Document your architecture. Write it all down and make sure that anyone can pick up the documents and be able to understand exactly what it is you are doing - write each document to the necessary type of person, e.g. an SDK document should assume software programming background; overviews should be aimed at your manager or your manager's manager and Joe Smoe off the street (not that Joe Smoe will get it - just anyone should be able to understand it given th

    --
    Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
  92. Implement a memory management layer by c0d3r · · Score: 1

    One of the most powerful techniques i've seen for c++ is to implement a thin memory management layer (gc, reference counting, caching and cache warming). This will make it stable to the level of JVM's and CLR's without a performance loss, assuming that all code uses this api (or simply preprocess on malloc and free). This can even speed up code significatly with hardware cache aware code.

  93. Python is second only to Love by James_Aguilar · · Score: 1, Insightful

    Python is the second best thing in the world, right after love.

    1. Re:Python is second only to Love by linguae · · Score: 1

      And for some of us Slashdotters (like myself), according to your theorem, Python will be the best thing in the world that is obtainable.

      Looks like I have another programming language to learn....

    2. Re:Python is second only to Love by Anonymous Coward · · Score: 0

      Lucky you, getting modded up by a Python fanboy. That means you don't need to give any reasons.
      Maybe some other people don't actually like Python?

    3. Re:Python is second only to Love by SpinJaunt · · Score: 1

      Still, you should know that you are better off learning ONE language and learning it thoroughly as opposed to learning every language, poorly.

      --
      /. is good for you.
    4. Re:Python is second only to Love by James_Aguilar · · Score: 0, Flamebait

      Maybe those other people should learn when I'm trying to be funny and when I'm trying to be serious? Do you think that I'm trying to make a logical argument by comparing Python and love? It's just supposed to be a tongue in cheek assessment of a language that I really do like, but not quite that much. You, on the other hand, are free to not like Python and, moreover, not use it, so I don't see the reason you should be complaining.

  94. General Advice and Some Reading Recommendations by mdakin · · Score: 1
    If you want stable software perhaps one of the most important things you can do to stack the odds in your favor is to keep your system as simple and clean as possible. The idea to completely decouple the application from itself seems complex rather than simple and thus could serve to reduce reliability rather than increase it. I really strongly recommend not getting that complex from the get-go especially without any empirical evidence indicating that the complexity is absolutely required.

    The restart logic to bring parts of the system up that fail also seems like it could have a net-effect of reducing reliability. Such restart logic will almost certainly be complex and thus problematic. I recommend instead a different error handling paradigm: whenever anything pathological is detected your program should "panic" (quit in a graceful way) and tell you exactly why it panicked (perhaps by printing out a stack trace, perhaps by printing out the exception's .what() string and making sure all possible exceptions produce uniquely identifiable strings.) In the course of development every time a panic happens you will know why and so will be able to resolve them quickly. Given this sort of discipline, some good engineers and the proper development schedule by release time you will have worked all the common panics out of the system.

    The advice to use some sort of agile software development process and automated unit-testing is spot-on. Check out cppunit (http://cppunit.sourceforge.net/cppunit-wiki). I use cppunit extensively and it helps me greatly. Making the application unit-testable will increase its complexity somewhat, but this complexity increase is usually not too great and will prove to be insanely worthwhile given the advantages of having an automated unit-tests testing that your software still works at every build.

    Think carefully about your Makefiles/directory structure. Again you want something simple. But you also want the build system to do some things for you like auto-generate the dependencies of your .cpp files and invoke your unit-tests as part of the build. Make sure you build system refuses to output an application binary if any unit-test fails (this is quite easy to do with make and cppunit.)

    The advice to utilize STL and exceptions is also very good. There is no need to reinvent the wheel when you can leverage STL. Make sure you do some reading about exceptions to avoid making a big mess, but they are absolutely worth learning and using.

    Really, really try to stay away from threads. Threads imply complexity and it is hard to get them right without great discipline and some experience.

    Reading:

    The C++ Programming Language by Bjarne Stroustrup
    This is worth having around as a reference. It is a bit heavy as a tutorial but it will be able to answer many the strange questions that come up about C++.

    Effective C++ Third Edition by Scott Meyers
    (Getting the THIRD (newest) edition in particular is important.) C++ has a learning curve that's a bit steeper than many of the other modern OO languages. This book helps you up that curve as quickly as possible (assuming you already know the basics of OO software design and languages.) Very good advice about why you should use the "auto_ptr" (that others mention) when you allocate memory on the heap. Advice about exceptions. Lots and lots of other lessons can be learned from a quick read that will save you so much time and pain the long run.

    Agile Software Development by Robert C. Martin
    Others may disagree with this recommendation. I think there are several similar books. This is the one that I happened to encounter and I do not know if it's the best. I do know it is sufficient at giving a broad overview of many important concepts like: agile development processes, unit testing, OO design principles, design patterns.

    Good luck with the system!

  95. language antics by Anonymous Coward · · Score: 0
    A question about how to write reliable software, and immediately we have a bunch of dufuses going on about language choice. Part of me wants to rant, but more of me just wants to cry.


    Consider: 30 years ago, software was written in assembler. Nowdays, it's written in a variety of higher level languages. In that time, has software reliability increased, or decreased?


    Note to the truly clueless: I'm not suggesting that assembler is better.

  96. Re:Yeah, c++ hasn't been successfully used before. by geminidomino · · Score: 1

    I wonder if that was included in the question not as a bash on C++ being unstable, but to try (unsuccessfully, as it turned out. This IS slashdot, after all) to ward off some of the inane "Use Python/.NET/Ruby/Visual Basic/etc..." posts.

  97. Unit Testing by Nova88 · · Score: 1

    Unit Testing anyone?!?!

  98. my experience by larry+bagina · · Score: 3, Informative
    I'd say try to have lots of little programs that do one specific thing -- easier to test and verify. Also, if (when) a bug is found it should be easier to fix, and hopefully will have less impact than if it was a monolithic application.

    I've dealt with software that automatically restarts a dead process, and in my experience, it doesn't work so good. If you want ultra-stable software, you want to know what caused the crash and why.

    For your situation, where I guess you're doing lots of time consuming computing, I'd think you should also set checkpoints, save intermediate results, or something, so if it does crash, you can restart in the middle instead of going back to 0. (A standard practice when I was analyzing large databases for corruption, a task that could take days)

    --
    Do you even lift?

    These aren't the 'roids you're looking for.

    1. Re:my experience by Keeper · · Score: 1

      I've dealt with software that automatically restarts a dead process, and in my experience, it doesn't work so good. If you want ultra-stable software, you want to know what caused the crash and why.

      It works better if your application does logging and creates dumps of the faulting process before restarting. Post mortem debugging can be incredibly useful.

  99. "How to write code that doesn't crash!?" by Abedneg0 · · Score: 1

    So your question is, "How can I write code that doesn't crash?" First of all, it doesn't matter which language you use. There is no language that will guarantee uncrashability. There is no "design pattern" that will guarantee uncrashability. If you are asking such questions, I think your best course of action is to find an experienced programmer to do it for you. They are not cheap, but it will be worth it in the long run.

    I've seen the most stable code written in C, and I've seen horrible mess in PHP and Python. It's like asking, "Which brand of circular saw should I use to make the best kitchen table?" A true hacker can make a work of art with an axe, and not because he is forced to, but because that happened to be the best tool for the job.

  100. Books to read, things to do by TheKingAdrock · · Score: 1

    Read all of Scott Meyer's and Herb Sutter's books. Practice what they preach. Investigate tools in finding memory leaks and use them from day one. Invest in infrastructure that helps you test code. Write unit tests. Insist on 100% block coverage on every piece of code that gets checked in, even if it means that you have to write a lot of stub functions that force failures (e.g. a version of operator new which is designed to throw an out-of-memory exception). Have at least one tester for each coder, if not more, and hire people who would easily be as good as your developers. Have the testers do code reviews as well as developers. Spend time refactoring code every time to go to write new code - make sure the existing code that you're attempting to modify actually makes sense in light of the changes you're making to the system. Use prepackaged code rather than inventing your own - too many teams rewrite pieces of the standard library or other libraries because they think they can do it better, or think that the existing code isn't efficient (although they haven't actually profiled it and don't know if it matters for their application). Basically - care about what you're doing and make sure every person on the project does, and you'll have much better success than the average team. Having people who care what they are doing and stay around long enough to see the job get done is worth more than many people give it credit for.

  101. The solution? by Anonymous Coward · · Score: 0

    1. Use Web 2.0 for your app!
    2. ???
    3. Profit!

  102. Follow the KISS (Keep It Simple Stupid) rule by Eldred · · Score: 1

    A few simple steps.

    1. Favor creating objects on the stack, rather than on the heap. Stack objects are automatically destroyed when they go out of scope. If you can't do it on the stack, try to destroy it in the same function in which it is created, barring that, destroy it in the calling object's destructor.

    2. If a library function exists that can do what you want done, use it.

    3. Keep functions as compact as possible. A short simple function that does just one thing is easier to get right/debug.

    4. Set your compiler to maximum nagging (-Wall in gcc), and fix your code so that it doesn't complain.

    5. Use structed exception handling. It will greatly improve the readability of your code.

    6. If you have to use allocated (malloced) memory buffers, create a class to "own" the memory buffer and access the memory via that classes member functions. That way you can take advantage of rule 1 for managing buffers as well.

    7. Code reviews. Have a group of peers review each and every line of code you write, preferably with you out of the room.

    I'm sure there are other things, but that is a good start.

  103. Listen to what he said!! by logicnazi · · Score: 5, Insightful

    Jesus christ people he is asking you how he should go about building an ultra-stable application in C++. He told you he *has* to build it in C++ because there are critical libraries and other components that aren't availible in C++. Telling him he shouldn't build it in C++ anyway just isn't helpfull.

    I hate to break it to people but there *are* libraries, especially for types of scientific computing, that are only (reasonably) availible in C++ or sometimes FORTRAN. Not only would abandoning these libraries mean he would completely have to reinvent the wheel but also might cause serious compatibility problems not to mention a much greater ongoing maintenence responsibility (he can't just check his program to make sure things still work when someone fixes a library bug).

    Moreover, the idea that because he is considering using CORBA, IPC or whatever else speed can't matter enough to require C/C++ is dead wrong. It is true that whatever *parts* of the process are done using these components may not require huge amounts of speed but this doesn't mean one of these components isn't doing something very processor heavy.

    In particular what he says sounds like the situation in some areas of scientific computing. If one is writing a program to do some sort of simulation or similar math intensive operations speed can be *very* important in the critical parts of the code but (in some cases) transfering information to the GUI or other components need not be particularly speedy (increasing by an order of magnitude may make a small difference in overall runtime). Imagine a program that does some kind of weather, or nuclear detonation simulation. The cross-processor communication and the core simulation kernel need to be very fast but the GUI and data input components need not be particularly fast. Also it is my understanding that often the critical libraries in this area are often only availible (at least freely) with C/C++ or fortran bindings.

    Anyway I think it is important to distingush several different goals, ultra-stability, minimal downtime, and minimal data/computation loss. For instance a climate simulation that may run on a supercomputer for months it is very important to have minimal data/computation loss (i.e. if something goes bad you don't lose months of very valuable supercomputer time) but you need not have ulta-stability or minimal downtime. As long as when any node crashes the simulation can easily be restarted without loss of data there is no problem. On the other hand if you are running a website like slashdot it is minimal downtime that is important it doesn't really matter if some of the web server processes are rebooted once in awhile. If, on the other hand, you are writing code to monitor a nuclear power plant it is ultra-stability that is important (though I can't at the moment think of something that requires distributed processing and ultra-stability but I'm probably just missing something).

    So I think the answer depends on what sort of stability you want. If it is important that no individual *node* crashes (though the GUI/other non-core components can crash) then you should pursue the seperation you described above. I have to admit I'm not an expert here but the client-server model (like mysql, X etc.) seems to work well in this context. However, this depends alot on what sort of data you need to transfer. If you just need to send the core setup commands and get back mostly unstructured info (say a grid of tempratures or other simple datasets) then I would suggest sticking with one of the simpler abstractions and don't get lost in CORBA. On the other hand if you need to send back and forth real objects with significant structure then creating your own serialization system/bindings is just asking for bugs.

    On the other hand if what you want is minimal data/computation loss, downtime, or any other property where it is the overall system you care about not a crash at any particular node then I suggest concentrating less on dividing any one node into comp

    --

    If you liked this thought maybe you would find my blog nice too:

    1. Re:Listen to what he said!! by Lumpy · · Score: 2, Insightful

      Jesus christ people he is asking you how he should go about building an ultra-stable application in C++. He told you he *has* to build it in C++ because there are critical libraries and other components that aren't availible in C++. Telling him he shouldn't build it in C++ anyway just isn't helpfull.

      And what he is asking can not be done BECAUSE of the libraries.

      you CAN NOT guarentee that the libraries are 100% stable. Typically I find that stability points to the libraries and you have to write your own to get your high stability.

      Granted this is from an embedded systems point of view. but if he is looking for ultra stable (5 nines) then he has to change things. Depending on XYZ library means that your stability can only be as stable as THAT library and some of them out there really suck at stability.

      --
      Do not look at laser with remaining good eye.
    2. Re:Listen to what he said!! by __aajudx8562 · · Score: 1

      a move to managed code would not involve abandoning c++ libraries - you can access unmanaged libraries from managed code. c# could be used to bind the whole thing together.

    3. Re:Listen to what he said!! by Surt · · Score: 1

      Still, he should consider managed code for the portion of the application under his control, and use native invocation for access to the libraries he needs. Then he can more confidently/easily blame the libraries when things break.

      --
      "Who is the Journal of Quantum Physics going to believe?" --Stephen Hawking
    4. Re:Listen to what he said!! by GileadGreene · · Score: 3, Informative

      So what he needs to do is develop a design that is robust in the face of errors. In other words, it needs to be fault tolerant. There are well-known design practices for doing this (checkpoints, watchdogs, rollbacks, etc.) as well as design patterns for robust distributed computation (see, for one example, Joe Armstrong's thesis on making reliable systems in the presence of software errors.

      No, the situation the OP is in is not ideal. But it's also not impossible to work with, and there are techniques that can help him to get closer to achieving his goals within the constraints placed upon him.

    5. Re:Listen to what he said!! by Anonymous Coward · · Score: 0

      Much text to disguise your fundamental error: There is no need to write the whole application in a single programming language.

      No nontrivial application needs to be completely written in C++ for performance reasons. Most parts will not be performance sensitive and some parts may benefit more from a sophisticated algorithm in a high-level language than from brute force bit shuffling in C++. Writing a C++ program that performs well also takes effort and skill, if you take "performance" for granted you won't get it, instead you just get the usual segfault.

      The sane advise is really to use a (much) better language. I'd suggest Haskell or some ML variant, but that's probably just personal preference. Paul Graham would suggest Lisp, which is again largely personal preference. Smalltalk, Scheme, Erlang or any number of "scripting" languages may also be an idea. Where performance matters, the program should call C procedures via a foreign function interface, which any modern language should have, or via IPC if that is considered anyway. At the very least, the GUI should not be written in "portable assembly", and neither should complex logic be. (What is complex? A binary tree is probably already too complex in C++. Not impossible, just hard to manage.)

      If C++ must be used for political reasons (and I suspect this is actually the case here), use good(!) libraries. Make as much use of the STL and Boost as possible. Try for a more functional, less object oriented and less imperative style. Put assertions everywhere (literally, you will never have too much range checks), then actually prove that they can never be violated. Of course, this will be next to impossible in C++. You cannot sharpen a pencil with a blunt axe.

    6. Re:Listen to what he said!! by shutdown+-p+now · · Score: 1

      What I don't understand here is, why does he have to write all of it in C++? Most (all?) modern high-level languages can interop with C (and, by extension, with C++). So why not make a wrapper around those libraries he has to use (low-level direct call mapping, or high-level abstracted wrapper, depending on what the libraries in question are), and then code the rest of it in Java, CL, OCaml or whatever it is.

    7. Re:Listen to what he said!! by Duhavid · · Score: 1

      There is nothing magical about managed code.

      Ending up in a catch handler because a reference variable
      is null ( nothing ) isnt much different from ending up in
      a catch handler because you dereferenced a null or bad
      pointer.

      And it sounds like he/she/it doesnt want to be able to
      confidently blame anything, he doesnt want things
      going wrong in the first place, or to be able to detect
      and recover when they do.

      He needs a great team, and to leave the technology
      selection to that team, once he has apprised that
      team of the requirements. If he is serious about this,
      he will find this team based on experience at building
      systems under similar constraints. And he will listen
      to the team on issues of tool selection, testing methodology,
      schedule, archetecture, platform, etc, etc.

      I'm sure he would like a magic bullet, but there isnt one.
      Care and time are required.

      --
      emt 377 emt 4
    8. Re:Listen to what he said!! by logicnazi · · Score: 1

      It is far from clear that this would make the application more robust and not less robust instead. All the magical features you get from managed code stem from the ability of the code to do automatic type inference and other types of validity checking. If the objects you are manipulating pass through an unmanaged section you can't automatically infer anything about them (except perhaps that they occupy x number of bytes and I don't know if you can even do this). Essentially you need to treat the objects from your C code as untrusted input and this is going to require a great deal of code and hence an increased likelihood of bugs offsetting the benefits of managed code.

      Worse just the fact of having the interface between the two languages can make garbage collection and other issues a nightmare. Who has the responsibility to dispose of objects? Can the managed code garbage collect objects it inherits from C++? If not all the sudden you need to do garbage collecting for some objects in your nice garbage collected language and when these start getting mixed with other objects things can get messy...there is a lot of chance for error with the wrong objects not getting GCed or incorrectly getting GCed.

      Also as the other poster pointed out whether of not managed code is very helpfull depends a lot on what kind of stability you need. If what is important is that the application just doesn't crash managed code is wonderfull. However, if you need to guarantee that it gets the right answer/doesn't screw up the overall computation (as say one might in some type of simulation) it is less beneficial. This is especially true when it is taking in data from unmanaged code. Essentially this just means you catch an error saying 'sorry object in wrong format' or 'unexpected value' and if there is no way to recover from this and continue executing you are screwed.

      Besides if you are writing something like a scientific application where it is very important that the computational core doesn't crash but the GUI/data input type stuff is relatively unimportant if it can be restarted you might as well just make the boundaries between C++ and managed code into boundaries between processes. Since you have to do something like an API anyway to interface your languages you might as well just do it as seperate processes so you don't need to worry about crashing at all.

      --

      If you liked this thought maybe you would find my blog nice too:

  104. Don't reinvent the wheel by DigitalCrackPipe · · Score: 4, Insightful

    Avoid the latest "big thing" for the core of your project. It's usually specialized, non-portable, etc. The standard template library for C++ (for example) is here to stay, with tested algorithms that are safer and faster than you can usually write (because they are optimized for the platform you compile on). For the GUI, on the other hand, you may be better off with a GUI-based language/tool. That's less likely to be portable, but that's the way GUIs work.

    Next, spend some time upfront on your design, with things like use cases, sequence diagrams, and other visualization tools to help you understand just what you want to happen in best case situations as well as failures. The level of detail/formality required is a moving target, so update as needed. You should have a solid error detection/correction plan so that you can design each component to follow it. Also design for test and with logging - it will help you while debugging, while testing, and while fixing the bug the customer is seeing.

    Make sure management will allow sufficient time for testing. A lot more lip service goes into support for testing than actual schedule and money. Your test plan should be as bulletproof as your design.

    That's my 2 cents. And a random book recommendation: books like Scott Meyers' "Effective " provide info on effective/error reducing ways to use the language/libraries, but won't help you get started with the architecture.

    1. Re:Don't reinvent the wheel by DigitalCrackPipe · · Score: 1

      D'oh. Mistyped the book title and used angle brackets. Should be "Effective C++/STL/~"

  105. Keep track of your memory. by Anonymous Coward · · Score: 0

    1) write an api that you use to do ALL of your memory allocating/freeing. Have it track allocations and frees and warn you when they don't match up at app shutdown. Have it fill memory blocks with fefe or some other pattern on release so that late references are crashes.

    USE IT FOR ALL ALLOCATIONS. Fix problems as soon as they occur.

    For the most stable possible code. DONT validate pointers - crashing hard during development is much better than having your parameter validation mask an error or bad assumption. Unless the code on the other end isn't your own code - in which case trust nothing. always fully validate at the interface anything that you didn't create. Better yet, don't use it at all.

    2) Dont use 3rd party componants. Insist on source code for anything that you call (with the obvious exception of OS functions).

    Managed code doesn't gurantee that you won't leak memory, it just makes the causes of leaks a bit rarer with at the same time making them MUCH harder to track.

  106. Run your code past PC-LINT by Weaselmancer · · Score: 1

    No kidding. It will catch things most humans will miss. Check it out here. If you want to get an idea of the kinds of things it'll catch, check out their "bug of the month" page - it's a facinating read. You'd be surprised how many nearly-impossible to detect errors you can make in C++.

    Disclaimer: I don't work for Gimpel, YMMV, etc.

    --
    Weaselmancer
    rediculous.
  107. Exactly how stable? by Sirp · · Score: 1

    It's hard to gauge exactly how stable this application is meant to be. If you write an application for almost any company they will say "yes it needs to be very very stable." But there is actually a large variance in that.

    For some companies, an application has to be very stable because the company might lose, say, $100/minute when it goes down. But this is actually toward the bottom end of needing to be stable, and is pretty typical for most business software. Real stability is needed when a crash could mean a loss of millions of dollars, or loss of life.

    Because you state portability to Windows as a requirement, I tend to doubt your application really needs to be that stable. Applications that need very high stability usually have one specified target platform.

    Whatever your requirements are, the number 1 way to achieve stable software is by using the KISS principle as much as possible. However, if your requirements are in the latter category, you will absolutely need to use KISS to the maximum. Don't allow new features. Make the application as stupidly simple as possible.

    Finally, you need to carefully consider what kind of 'stability' is needed. For software that needs to be super 'stable', producing the incorrect results can actually be worse than a crash. Writing code that is completely bug-free is much harder than writing code that simply doesn't crash.

    In C++, the best approach is to take advantage of the type safety features of the language. Don't use things like void pointers, and use STL containers and so forth rather than allocating memory yourself. Keep the programming team as small as possible, and carefully vet the code.

    If the program is truly in the "needs very very high reliability" category, then yes, write unit tests. If it's actually in the "complex program that we're going to add lots of features too, but we'd kinda like it to be stable too" category then unit tests are probably going to be a waste of time.

    -Sirp.

  108. C++ tips by Anonymous Coward · · Score: 0

    * Minimize logic redundancy.
    * Minimize use of unsafe data structures and operations. Write or use existing checked wrappers around arrays, pointers, dynamic memory allocation, casting, etc. So that it just isn't possible to run into the problems that these things can cause.
    * Try to make it impossible to write things incorrectly by taking advantage of the compiler. Use classes with limited interfaces so you can't call the wrong methods.
    * For things you can't check at compile time, check them at run time. Use lots of assertions. Constantly check that pre-conditions, post-conditions, and invariants are maintained.
    * Do unit testing, system testing, and every other kind of testing for anything you can't check at compile time.
    * Make the assertions be exceptions for production releases and use good exception handling techniques.

  109. THIS IS JUST WRONG by logicnazi · · Score: 1

    This statement is just ignorant and wrong. I don't want to flame the original poster, he probably just didn't think about it too much and made a mistake, but it is even worse to mod this up to 5.

    It is a well known fact that a huge percentage of processor time is used by a small percentage of the code. It is very important for that code to be fast because it is inside a loop being executed millions of times and perhaps this requires a language like C/C++ however other parts of the code which execute once for every million times the performance critical code runs can often be orders of magnitude slower without affecting overal performance.

    Just as an example consider something like the GIMPS project or one of the RC whatever challenges. It is vitally important that the tight inner loops be very fast but you could write the graphic output and network components in a shell script that calls command line packet/output programs written in java and it wouldn't slow the overall app much.

    --

    If you liked this thought maybe you would find my blog nice too:

    1. Re:THIS IS JUST WRONG by rjstanford · · Score: 1

      So I said:

      Even as stated, I would write the core in a highly tuned fashion (although C++ might not be my best choice for this), then write the GUI in the language of your choice, quite frankly. Optimise the bottlenecks (ie: your core processing) for speed, optimise everything else for maintainability and ease of development.

      And you said:

      This statement is just ignorant and wrong ... It is vitally important that the tight inner loops be very fast but you could write the graphic output and network components in a shell script that calls command line packet/output programs written in java and it wouldn't slow the overall app much.

      Well. Thanks. That makes so much more sense than my original WRONG post.

      --
      You're special forces then? That's great! I just love your olympics!
    2. Re:THIS IS JUST WRONG by logicnazi · · Score: 1

      Sorry, I made a mistake. Someone who had posted before had made the remarks I had meant to be critisizing and I stupidly just skimmed your post and thought it was the same.

      Well I guess the egg is on my face. I'd mod myself down if I could (hmm..I wonder if that would be a good feature)

      --

      If you liked this thought maybe you would find my blog nice too:

  110. robust software by avitzur · · Score: 4, Interesting

    Way back in 1993, thanks to a three month schedule delay in shipping the original Apple Power PC hardware, Graphing Calculator 1.0 had the luxury of four months of QA, during which a colleague and I added no features and did an exhaustive code review. Combine that with being the only substantial PowerPC native application, so everyone with prototype hardware played with it a lot, resulted in that product having a more thorough QA than anything I had ever worked on before or since. It also helped that we started with a mature ten year old code base which had been heavily tested while shipping for years. Combine that with a complete lack of any management or marketing pressure on features, allowed us to focus solely on stability for months.

    As a result, for ten years Apple technical support would tell customers experiencing unexplained system problems to run the Graphing Calculator Demo mode overnight, and if it crashed, they classified that as a *hardware* failure. I like to think of that as the theoretical limit of software robustness.

    Sadly, it was a unique and irreproducible combination of circumstance which allowed so much effort to be focused on quality. Releases after 1.0 were not nearly so robust.

    1. Re:robust software by danielDamage · · Score: 1

      Pretty impressive that you actually spent those few months constantly stabilizing and improving the program instead of surfing porn on the internet and saying you were doing same.

      --
      Slices, dices, eats your lunch.
    2. Re:robust software by dunkelfalke · · Score: 1

      this was 1993. much less porn and internet back then.

      --
      Conservatism: The fear that somewhere, somehow, someone you think is your inferior is being treated as your equal.
    3. Re:robust software by Anonymous Coward · · Score: 0
  111. Make it OpenBSD native... by Anonymous Coward · · Score: 0

    With the security fixes put into OpenBSD, it would be helpful to make your programme run on it natively - the fixes they have make programmes crash rather then allowing them to be exploitable, you'll be finding bugs much easier on it.

  112. Most stuff is already covered by Keeper · · Score: 1

    A few areas I haven't seen covered:

    * If you are going to be consuming code you don't own, for the love of god run it in an external process. Create a defined plug-in like interface that your customers will use, and have a shim process designed to load the plug-in and perform communication back and forth with your real app. Your real app should assume that every attempt to communicate with the external process will fail and respond accordingly.

    * Don't assume that hardware is fault free; assume that any and every operation than can fail will. I have personally tracked down application crashes that were the result of faulty hardware; in one instance, a machine had failure rates 20% higher than the rest of the machines -- turned out the mobo was faulty. In another instance, a harddrive was failing. I had one case where an object was allocated, verified not null, and passed in as a reference to a function -- which failed because the object was null...

  113. Re:Yeah, c++ hasn't been successfully used before. by dezert_fox · · Score: 2, Insightful

    He didn't complain about anything... you added that part. He asked for advice. Were more people to do so, instead of relying on their overconfidence (like you) to get jobs done, maybe we wouldn't have computer instability be such an issue.

  114. Use a Tandem... er, 'HP Nonstop' platform by tjanke · · Score: 1

    You want extreme reliability? Put the app on an HP Nonstop, use some system calls to checkpoint the data to the app's backup process at key points in the processing, and voila! If the app crashes or the processor goes down, the backup process will takeover in less than 15 milliseconds, and continue processing. And yes, you can do it in C++.

    A potential drawback: last time I knew, the cheapest two-processor Nonstop you could buy would set you back $250k.

    The Nonstop is designed from the ground up to be extremely robust and reliable. That's why 80+ percent of all the ATM transactions in the world are handled by a Nonstop computer back at the bank's data center. 90+ percent of all the world's stock exchanges run on Nonstop machines.

    (Full disclosure: I have never worked for HP. I spent 12 years working on Tandem computers, 6 at Tandem HQ. Compaq bought Tandem, then (as we all know) HP bought Compaq, and so through them acquiring a company founded in 1978 by 3 ex-HP engineers. The formerly Tandem platform is now called the HP Nonstop.)

    --
    Cheers, Tim -- Tim Janke Part mad scientist, part lion tamer: sr. software engineer, global team leader, project mana
  115. "Crash only software" by haeger · · Score: 1
    I find the concept of "Crash only software" rather interesting. Perhaps something to have a look at?
    Crash only

    .haeger

    --
    You are not entitled to your opinion. You are entitled to your informed opinion. -- Harlan Ellison
  116. 3 Keys: People, Environment, Subject, by Morris+Schneiderman · · Score: 1

    A lot of good stuff has been posted in this thread, but let me add a little more.

    Success in a project such as this one requires an approach that pays attention to three factors. Ignoring even one of them will guarantee failure.

    1. People: Can you use a design & development team of one person? If not, communication will be crucial. Get the best people you can who are willing to work together. Your people need experience working together.

    2. Environment: Your team will need to be intimately familiar with both the development and live environments where this application will run. No one can be permitted to alter these environments once development starts. Don't even let them change the Uninteruptable Power Supply. I've seen a defective UPS introduce seemingly random errors into a rock solid production system! No other applications. No OS upgrades. Nothing!

    3. Subject: You can neither design nor write good code if you don't fully understand the subject matter. What does the application do? Why is it important that this be done? Where does the input data come from? How and why is it generated? Who will use the outputs from your system? What will they do with those outputs? Why?

    If your requirements are as stringent as you claim, select your team up front. Do not add anyone to the team (designers, coders, testers, documenters, project managers, etc. ) once you start the process outlined below. Everyone needs to be in it "for the duration".

    Don't plan to do just one project. Plan for the team to do five projects using the environment. Plan for enough time to do it right. Plan for enough time for your people to get enough sleep. Plan for your team to not do any other applications until this one is finished. Do not reuse any code from project to project. The first four projects are learning projects.

    Project 1: Team Building Project - Pick something relatively easy. The primary purpose of this project is for the team to become familiar with each other. The secondary purpose is for them to become familiar with the environments (OS, development tools, test tools, etc.) But this project (and all the others) must be taken seriously and produced to the same standard as your final product.

    Project 2: Environment Test - Pick something that will push the environment to it's limits. Use every feature of the languages. Process numbers that are extremely small and extremely large. Process strings that are empty. Process strings that are huge and that contain all possible characters. Include all the "corner cases" you can imagine. Run it under high load, light load, no load and variable load. The purpose is not just to prove the environment, it's also for the team to gain an understanding of how the environment pushes back.

    Project 3: Subject Matter Test - Pick something relatively simple to give your team experience with the subject matter and data that will be used in your ultimate project.

    Project 4: Trial Run - Do a simplified version of your ultimate project. This is the place where your team gains experience with the core of the problem they will be addressing in the ultimate project.

    Project 5: The Real Thing - This is where your team finally delivers what is wanted. Use a minimum of language features and system resources. Avoid doing anything "fancy". Keep it simple and organized. And remember, don't reuse any of the code from the earlier projects. Just use that you learned.

    See, it's really easy. I've been producing high quality code for more than 35 years. And I learn something new on every project. This methodology won't guarantee success, but it sure will help you get there. Good luck.

    Morris

  117. And Remember to Design a Testable System by david_costanzo · · Score: 2

    I completely agree with the parent, but I want to add a few things.

    Before you do your design, you should try understand all of the system's requirements. Just how much reliability is really needed? Are lives at stake? Is a lot of money at stake? Is a system failure just inconvenient? Remember that each extra "9" in reliability multiplies the cost of the project by 10, so make sure you understand just how reliable your system must be before you start.

    Once you understand the system's requirements, make sure that your fault-tolerant design is testable. Then design your tests (before you write a single line of code). Don't make the mistake of leaving testing until after implementation. Make sure all of your interfaces are specified and that the subsystems are decoupled enough such that you can test each unit individually and thoroughly. What happens if a subsystem receives bad input? What happens if a subsystem takes longer than expected to respond? How long is too long? What happens if a subsystem returns bad output? You should design your system such that you can replace any subsystem with a misbehaving (test) subsystem and that your overall system responds appropriately. In the process of designing your test, you should expect to find many design defects (or design glosses).

    You should also get someone to peer-review your design (and your tests) with the mindset of making your system fail. People with different backgrounds will have different experiences of what can go wrong; don't expect that you have thought of everything yourself.

    By now you may be thinking "that's a lot of extra work". You're right, it is. But it's all necessary. You can scale back some of this depending on how much reliablility you actually need, which is why it's essential that you understand your requirements. You also don't have to do all the work yourself. In fact, you probably shouldn't. You should get someone else to work on the test side of things.

    By the way, one essential subsystem to modularaize is the allocation of resources. You will find a lot of defects just by inserting a memory allocator that occassionally simulates out-of-resource conditions. There are tools to do this, but they don't seem to be portable to different operating systems.

  118. Write it right the first time. by www.sorehands.com · · Score: 1

    If you focus on writing the code right the first time, then it will be more reliable. Try programming it as though the user is a homicidle maniac that knows where you live.

    But seriously, use lint, Electic Fence, and all the tools you can to test the code.

  119. Re:Yeah, c++ hasn't been successfully used before. by Anonymous Coward · · Score: 0

    disturbed

    please, that is clearly not a typo, but an acte manqué

  120. You are so close! by Anonymous Coward · · Score: 0

    You don't want it to be crash proof, you know in your heart of hearts it will crash.

    You want to design it to keep working regardless of the failures you know will happen.

    Assume there will be failures and design it to work anyway. That is the correct starting point. Then worry about the technical side of things and for that I leave it to others to contribute.

  121. do what computer scientists do, or get a lawyer by wikinerd · · Score: 1

    First advice: Use modularisation at its extreme. Second advice: After finishing your UML model, create a mathematical model too using automata such as finite state machines and formal methods or other software engineering techniques. If the model works well mathematically, there is good chance that the software conforming to the model will work ok too... in theory. In practice, I advise you to hire a good lawyer to write you a thorough disclaimer.

  122. Re:Yeah, c++ hasn't been successfully used before. by Lehk228 · · Score: 1, Funny

    write a perl interpreter in C++, then have the perl program stored in a string within the source file. that way it is still in c++.

    --
    Snowden and Manning are heroes.
  123. Your reasons are crazy by k8to · · Score: 1

    Both your reasons for staying with C++ are insane. There are plenty of other execution-efficient languages, and interfacing with libs is something every language pretty much has to be able to do.

    Your other ideas also cut directly against simplicity and execution efficiency in a lot of cases, so dogmatically insisting on C++ is stupid.

    That said, language is not your largest problem. Investigate provably correct software, less than perfect proofs, tools for evaluating code for correctness in automated manner, test first development, and lots of other things. And hire someone more experienced than yourself, you clearly don't have the background to pull it off.

    --
    -josh
  124. Three things ... by jgrahn · · Score: 1
    Three things:
    1. We have no way of knowing what "ultra-stable" means ... the requirements are not clear to me, so I'm extrapolating a lot.
    2. The best way, IMHO, to create working programs is to make them simple, to the point of cutting away features. You mention a GUI, database storage, distributed computing and numeric programming. Mix those together and I promise a disaster or a late project. If you can, make the GUI a separate thing, not vital for using the thing. Same thing with the database stuff.
      For the distributedness, CORBA has always seemed like a good way to end up in a mess. Is it possible for you to split the computations on process borders, and maybe use ssh to distribute the work? At least for prototyping?
    3. C++ is a good language for writing big stable applications, but you need people who write modern C++. C++ was a terrible language back in the mid-1990s, and many people still use it that way. Look for people who understand the RAII concept, and the standard library. Avoid those that use C strings and C arrays, and have new/delete sprinkled everywhere in their code. And, come to think of it, avoid the Java programmers as well -- the people who always find an excuse to introduce abstract base classes everywhere ...
  125. Cowboy Modeling. by Anonymous Coward · · Score: 0

    "I need to create an ultra-stable, crash-free application in C++. Sadly, the programming language cannot be changed due to reasons of efficiency and availability of core libraries. The application can be naturally divided into several modules, such as GUI, core data structures, a persistent object storage mechanism, a distributed communication module and several core algorithms. Basically, it allows users to crunch a god-awful amount of data over several computing nodes. The application is meant to primarily run on Linux, but should be portable to Windows without much difficulty." While there's more to this, what strategies should a developer take to insure that the resulting program is as crash-free as possible?
    "I'm thinking of decoupling the modules physically so that, even if one crashes/becomes unstable (say, the distributed communication module encounters a segmentation fault, has a memory leak or a deadlock), the others remain alive, detect the error, and silently re-start the offending 'module'. Sure, there is no guarantee that the bug won't resurface in the module's new incarnation, but (I'm guessing!) it at least reduces the number of absolute system failures.

    How can I actually implement such a decoupling? What tools (System V IPC/custom socket-based message-queue system/DCE/CORBA? my knowledge of options is embarrassingly trivial :-( ) would you suggest should be used? Ideally, I'd want the function call abstraction to be available just like in, say, Java RMI.

    And while we are at it, are there any software _design patterns_ that specifically tackle the stability issue?"


    Gee! All that, and there's no modeling? Is everyone around here a cowboy programmer?
  126. Do not trust by padamj · · Score: 1

    I have written applications that run on low memory frootprint devices, offer complete CORBA Interfaces for CSAF-Configuration, Status, Alarms and Faults integeration few a dozen EMS.

    I use ORBit2 for both the client and server side... it's almost natural once you know how.

    I have a few pointers for stability:
    1. A function should be of return type void if and only if the failure inside that function is non-critical.
    2. Every possible function should have a return -- and failures should be trapped gracefully and all the way to the top.
    3. try-catch-exceptions --- wrap a lot of your code to catch exceptions... and use these consistently.
    4. And finally... do not trust any entity. Do not make any assumptions about things like a function succeeding, memory getting allocated etc. I call this is a "failure assumption mode" where I trap failures first, then handle successes later.

    Also, if possible go through some general linux kernel code. Though it is coded in c, and is a monolithic kernel, you can see a lot of graceful handling of failures.

  127. You'll Want To Use Erlang by Anonymous Coward · · Score: 0
    Erlang was originally designed by Ericsson for real-time telephone systems. But see the Erlang FAQ first.

    Erlang is used in Ericsson's phone systems, is now FOSS, runs under Windows & Linux and is rock-solid, unlike C++. You can even buy support for Erlang if you so desire.

  128. Re:Code generators, managers, frameworks, develope by general_re · · Score: 1
    Also, restarting a process and hoping the crash does not happen again is not in general the right thing to do, as students of the Ariane V disaster will realize. In that case there were multiple redundant processors that all had the same bug (relative to the inputs they were getting from the new vehicle).

    Actually, IIRC the Ariane software didn't attempt a restart, and it wasn't really a crash per se, although if it had attempted a restart, the result would have been the same. Anyway, as I recall, each control system (two redundant systems) was designed to assume a hardware failure and shut down upon receiving inputs that were outside a certain range, and thus leaving the second (working) system in charge. Except that they slapped an old system in from the Ariane IV and didn't bother to test it against the flight profile of the new rocket, so upon getting out of range inputs, both systems duly shut down as designed, thereby leaving nobody to drive the bus ;)

    --
    ABSURDITY, n.: A statement or belief manifestly inconsistent with one's own opinion.
  129. Be ruthless. by sampowers · · Score: 1

    DESIGN DESIGN DESIGN DESIGN
    TEST TEST TEST TEST

    Every function, every class, every file, EVERYTHING, needs to have automated tests associated with it. Keep in mind that it's really tough to write tests after the fact. You need to do it as soon as possible, and you need to enforce their use, preferably by automated means.

    Use revision control, even if it's just you doing the coding, so you can add a post-commit hook on the server end to compile and run your tests, and raise some sort of red flag if anything fails.

  130. Use the Standard Template Library by medoc · · Score: 1

    One of the most common causes of crashes for C/C++ applications is quite obviously memory management (bad allocs/deallocs, overflows, etc.)

    You can get very much more secure in this area if you use STL tools as much as possible, and let strings and containers handle the memory allocation issues.

    You gain a lot of time, more readable code, and also faster one in most cases because the STL algorithms are so highly optimized (I've more or less renounced trying to outsmart the STL with hand-crafted code...)

    Reducing the number of explicit 'new' calls in the program is, in my experience a significant factor in stability.

    MySQL, for example, is STL-based, and I think this is one of the reasons why it has been extremely stable since the beginning (at a time when it was not obvious to make this choice because of compiler issues).

    Another positive aspect is that, because containers are so easy to use, you don't hesitate doing complicated data management tasks that might seem undauntable when hand-coded. On this aspect, this makes C++ closer to interpreted languages with, for example, ready-made associative arrays and automatic memory management.

    JF

  131. Discipline by Leknor · · Score: 1

    First, this is a discipline issue. Your language or tools won't make your code rock solid, only you can. Based on the wording of the question I doubt you are experienced enough to achieve your goal with out a lot of self education.

    For example you say hiding of the abstractions like Java RMI is desirable. But what Java RMI hides it what makes it unsuitable. The fact is a remote method call could fail for a number of reasons and pretending a remote method call is just like a local method call won't help you write rock solid code. Use a messaging system that doesn't pretend things are simpler than they are.

    Don't use cutting edge, buzzword-worthy, technology. A mature technology will be more robust and have fewer bugs.

    Humble yourself some. Unless you are a programming god, which you aren't because you're asking slashdot for help, your code will have many more bugs than the mature libraries you use. I love how your decoupling statement is based on errors in "say, the distributed communication module" as opposed to your own code where it's much more likely.

  132. References by prockcore · · Score: 1

    Two tips:

    One, use references not pointers. The compiler is very good at detecting wonky things when you're actually dealing with objects and not just pointers to objects.

    Two, use STL wherever possible.

  133. good coding techniques by Pr0xY · · Score: 4, Informative

    first and foremost, use good coding techniques. This means use exception handling where appropriate, use standard containers over hand rolled data structures (prefer std::string over char arrays, this will help prevent almost all common string based buffer overflows alone), and follow good style guidelines.

    As for a GUI programming, if you are strictly tied to c++, i would recommend QT (www.trolltech.com) they have a fabulous API (takes getting used to, but it makes sense once you do). Nice part about QT is that it is source portable to just about every major platform (X11, Win32, Mac).

    It is possible to write reliable, fault tolerate code in c++ (realize please that perfect code is impossible in any language), it just has to be well thought out and done right.

    proxy

  134. Overload it to test and restart frequently by thaig · · Score: 1

    I had to find a bug that caused a crash approximately every 2 weeks. It was terrible to debug because we couldn't replicate it initially. I eventually wrote a system test that shunted about 2 weeks data through the system in an hour but using random rates and delays and I simulated comms failures by killing the test process and restarting randomly. I found the bug in a comms error handling routine using purify (you could use valgrind). It was a double-free that corrupted the stack and caused a crash somewhere else later on, sometimes. The customer account was saved.

    The lesson, to me, is to write a test program which will simulate heavy but randomised use of your system and to then to use this against the system whilst running it in a memory debugger.

    In addition, I would suggest that you don't really need to split the program into several processes but would probably benefit from restarting the single process every day at some low usage period or by starting a new process and handing off to it from the old one. This idea always invites derision from my colleagues but they do make just as many mistakes as me and most of these mistakes wouldn't result in costly support time and patch creation if the software was restarted often.

    Regards,

    TIm

    --
    This is all just my personal opinion.
  135. Back to development Basics.... by deggy · · Score: 1

    I take it by 'stable' you mean 'reliable' rather than 'someone's life actually depends on it'??

      If someones life depends on it for christ sake don't use any of the high level languages, that's what languages like ADA were written for - but it'll mean a long development cycle and serious cash.

      If you just want cast iron reliability (banking sector reliability) the best advice is to get back to basics with the development - don't try to do it on the cheap, because it'll fail - don't let anyone you don't trust do it. It will go over budget and it will take longer than planned but use a proper development model (Booch, for example) and propper integrity testing (Z for example) and be prepared for a long haul.

  136. "3. NEVER ASSERT!!!!" ...? by neutralstone · · Score: 2, Insightful

    I really think you had better qualify this.  IMO, assertion failures do not *cause* problems; they are messengers, and the message is always this:  "Your program is broken."

    I don't think you want to *recover* from a broken state.  I think you want to debug it -- find out what went wrong, fix the code, recompile, test, and re-deploy.

    Because, if you get to the point where an assertion fails, it means the state of the program is corrupted, and therefore you can't trust any part of it; e.g., you can't trust error-recovery code to be well-behaved.  The best you can do is bring everything to a halt and fix the bug.

    There are rare exceptions (no pun intended) to this rule, but for the most part, if you write out a condition and say, "if this is false, then the program has a bug", then you have some explaining to do if you *don't* want to use an assertion.

  137. Wow, flame war central... by Duncan3 · · Score: 1

    I don't see one post rated above 2 that isn't a language flame.

    How about the same it's always been.

    1. Design it well.
    2. Hire good people (yes this rules out outsourcing of any kind, they dont give a damn about your code, only your money).
    3. Test it.
    4. Test it again.

    Language doesn't matter, testing does. But testing costs money, and that's bad, so just use Java, noone EVER makes an error in Java - or Python/.Net/Ruby or whatever the hype of the day is when you read this.

    Good grief.

    --
    - Adam L. Beberg - The Cosm Project - http://www.mithral.com/
  138. code formatting by neutralstone · · Score: 1

    By the way:  to get good formatting for code, use the "Code" format (see the drop-down menu next to the "preview" and "submit" buttons).

  139. A few guidelines by pornking · · Score: 4, Insightful

    The suggestions I have seen here so far seem to boil down to "Don't do it that way". Sometimes that's not possible. If it truly has to be C++, and it truly has to be as fast as possible and as bug free as possible, there are a few guidelines that can help:

    1. Unless the GUI will be I/O bound, and that's unlikely, try to write it in a safer language that has better GUI support.

    2. Make all your classes small and simple, and create test harnesses that are as complete as possible. Try to make the classes simple enough that they can be individually tested in such a way that all code paths are exercised.

    3. Check your arguments. This includes checking for invalid combinations, and arguments that are invalid given the state of the object.

    4. Don't use new or pointers directly. If there may be multiple references to an object, then reference count it and create handle classes that hold the references so all instantiation is controlled, and all destruction is implicit. Make these handles STL compatible, and never pass around pointers to them.

    5. Try to design the application to fail fast and recover from failure. For example, maintain the state of work being done in discrete transactions that can be aborted if a failure is detected. This can be on disk or in memory depending on your performance needs. This could be combined with the ability to restart the app in a new process and have it pick up where the last one left off.

    6. Have the app keep track of its memory usage, and be prepared to recover from memory leaks, possibly by restarting as in item 5.

    7. If the compiler you're using supports structured exceptions, then use them. They can degrade performance a bit, but they can also enable you to recover from NULL pointer exceptions.

    8. If you have multiple threads, then to avoid both the performance hit from context switches and the chance of deadlocks, don't let them access the same data directly. Instead, have them communicate through lock free queue structures. That way, all your main threads can pretty much spin freely. Spawn worker threads for any I/O or other operations that can block. A context switch can take as much time as thousands of instructions. You want to use as much of every time slice as possible.

    9. Keep the number of main threads down to the number of CPU's or less. That way, except for the times when the CPU is being used by the OS or other processes, (should be relatively rare) each non blocked thread gets its own CPU.

    10. Have an experienced QA team, that understands their job goes beyond unit testing.

    Now here's a few that are always important, but for what you want to do, they become critical.

    11. Have the design laid out at least roughly before you start.

    12. If at all possible, don't let requirements change in midstream.

    13. Overestimate the time it will take very generously. You will probably still be crunched.

    --
    pornking
  140. False Start by Jekler · · Score: 1

    I'd say to design a crash-free program you'd want to go back to the starting line. Deciding what language to implement a feature, module, etc. in should really be a final step in designing a program. You can design virtually every aspect of the program without implementation language ever coming up.

    It's much easier to understand if you step back a bit, think of programming languages as tools. Would you rush up to an architect and say "Alright, I've got this idea for a building but before we get started let me just say it must be done using only a ball-peen hammer and a flat-head screw driver."

    Seperate design and implementation, decide how your program works, what it does, what it looks like... The architect does not worry about what tool the construction workers will use to accomplish each task. When you have an idea for a program, why would you worry about which language each module or component is written in? If it accomplishes your task and meets your performance and stability requirements, isn't language irrelevant?

    If an architect arrives at a building site, and the structure meets his specifications, why does he care what kind of hammer the construction crew used? For all the architect should care, the construction workers could have driven the nails in with the palm of their hand.

    Decoupling, design patterns, data structures, GUI, persistent object storage, Linux, portable.... you've tossed in just about every trendy technical jargon a person could say in one breath. Without a deeper understanding of the construction of software, you are paying only lip service to any of these concepts.

  141. Pretty easy. Perfect solution: by Hurricane78 · · Score: 1

    Write some wrappers for haskell and then use haskell's fully deterministic type-safe behaviour in the right way.
    Then logically *prove* that your deterministic code does what it should.
    Now you only have to worry about the non-deterministic part.
    So keep it as small as possible under any circumstances!!!

    Then be sure to modularize your code in a way that allows runtime replacement (of parts where you forgot some exceptional possibility a by fully proven and unit-tested new module) for that case of some problem, that *WILL* happen (but will not be a problem if you work that way)!

    If you can't use haskell in *any* way, try to create fully deterministic and type-safe (think *micromanagement*) code WITHOUT state-dependend objects for everything where you would use haskell.

    I've some pretty advanced design patterns here, but i can't draw them right in here....

    --
    Any sufficiently advanced intelligence is indistinguishable from stupidity.
  142. Web Services by Rodness · · Score: 1

    Provides very good decoupling for anything that can be abstracted to a request-response model.

    XML is used extensively (if not exclusively) for data formats, and HTTP is used as a network protocol, keeping these to known standards keeps it simple.

    I recently used gSOAP (http://gsoap.sourceforge.net/ to implement some web services into a C++ API and it worked flawlessly.

    1. Re:Web Services by fathom108 · · Score: 1

      I'm thinking of decoupling the modules physically so that, even if one crashes/becomes unstable (say, the distributed communication module encounters a segmentation fault, has a memory leak or a deadlock), the others remain alive, detect the error, and silently re-start the offending 'module'.

      AFAIK gSOAP doesn't come out of the tarball with fail over. Also, why waste all that CPU encoding and decoding XML if you can avoid it? And HTTP is a crappy protocol unless you are using it for hypertext. You might consider ICE. You can also optimize communications down to in-proc function calls when critical by taking advantage of the co-location optimization feature. Try that with web services!
      As far as not crashing, minimize the use of naked pointers and use RAII and C++ becomes a very high level language.

  143. high integrity code is by good process by Anonymous Coward · · Score: 0

    I've done 2 summers worth of internships at a software development company who specializes in various safety-critical applications. The kind of question you're asking must obviously come up with you're talking about software that keeps a plane in the sky, or life-saving medical equipment functional. Even though nobodys death seems imminent if your program crashes, the same kind of approach could be used I suspect. I think the key is really a well defined process. I'm sure there are plenty of good books written about the subject, but the long and the short of it is this in my opinion: Detailed requirements that all trace directly to code (and there is no code that doesn't trace back to a requirement), and testing that validates each and every requirement. As for the modular approach you described, the projects I worked on were generally embedded and used operating systems designed with the sort of no-nonsense approach you talked about. Maybe considering the concepts used in these OS's would yield some ideas for your own application?

  144. Time by convolvatron · · Score: 1

    I'm suprised this didn't come up in any of the other discusisons. If the
    application requires stability, then you will need time. lots of it. it
    doesn't matter how many developers you have its going to take time to
    cook. if the powers that be cant give you 2-3x over what would the nominal
    development cycle would be, then just forget it outright (or maybe
    stability isn't all that important?). enough time any you could possibly
    employ the write-it-twice strategy (which i've never known to succeed
    in practice)

    aside from using a better environment (sounds like erlang might be perfect
    for you), the only other thing i could suggest that i haven't seen here
    would be reviews. long boring group sessions with a projector. 1 on 1
    peer reviews. print the thing out and take it to the bar with you and
    make sure that its obviously correct before you even bother having someone
    else go over it.

    your suggestion about restarting failed components is really looking at
    the problem from the wrong angle i think. what about correctness? build
    it properly in the first place

  145. Human QA by Tom · · Score: 1

    No matter how you code, there will be bugs. Aside from all the good advise others have given here, what you also need is a human QA. And I don't mean two half-assed testers. I mean hiring a bunch of people with evil glances in their eyes who could code the stuff themselves and pay them on a number-of-bugs-found basis. Give them every incentive to be as mean to your code as they can possibly be. You and the other coders will hate them, but they'll find anything that can be found in testing if you can make "I found a bug" something they can be proud of.

    --
    Assorted stuff I do sometimes: Lemuria.org
  146. Wheres Stroustup.. by Flaming+Death · · Score: 1

    when you need him.. so many experts, so few answers.

  147. Naturally, keep it simple, and other stuff by dtfinch · · Score: 1

    The less code there is, the fewer bugs you should have. This sounds like at least two or three programs, a GUI/controller and the nodes. Try to avoid threading, or any situation where there might be unexpected timing related interactions. And you make it clear that C++ is unavoidable, but does it all have to be C++? Or just the parts that need to be fast? The GUI could be managed. The node could be split into a managed program that starts an unmanaged program with a set of parameters and reads the results. Even if both parts were unmanaged, you'll still have a system where a single crash wouldn't crash the node entirely, but likely just the worker half of the node, which can be restarted by the monitoring half. And you mitigate a lot of memory leaks if your worker processes get restarted from time to time.

    As far as how to handle crash recovery, whether the program should fight tooth and nail to overcome the error, ignore (but log) the error, crash and restart upon error, or crash until it's restarted manually, it really depends on the severity of possible errors, and the consequences of failure vs incorrect behaviour. Is this a program that you'll be unable to patch in a timely fashion if it breaks? Obviously you'll want to run a lot of stress tests before the thing goes live, and consider how it'll respond to bad data.

    I have a credit card processing proxy (about 3 pages of javascript) in place to protect us from the outright dangerous credit card handling in our ERP system. The proxy just sits in the middle and blocks the unwanted transactions, returning fake replies to make the ERP system happy. Apparently our use of the ERP system is a little atypical, like sometimes shipping orders and charging cards on the same day the order was taken. Because its job is so important, if there is an error, I'd rather have it crash than take a chance that it might do something really bad. Most errors crash the proxy outright. The proxy is run by another script that mostly just sends me a message when it crashes. I like to live just a little dangerously, so the proxy gets restarted once after its first crash. But if it crashes a second time, I must restart it manually.

    On the other hand, I sometimes write code that ignores most unexpected errors, so long as it's worse to completely fail than to partly fail, and it's not doing anything expecially important or dangerous. For important things, it's often better to fail than to not fail when it should.

  148. "Don't use exceptions" ... huh? by neutralstone · · Score: 1

    Perhaps I misunderstood, but it seems that you're advocating the use of error codes instead of exception throwing/catching.

    Quoth Herb Sutter and Andrei Alexandrescu (C++ Coding Standards, item 74): "Report errors at the point they are detected and identified as errors. Handle or translate each error at the nearest level that can do it correctly."

    And then there's item 72, which is pretty lengthy and contains lots of references:

    "Prefer to use exceptions to report errors.

    "Summary

    "Prefer using exceptions over error codes to report errors. Use status codes (e.g., return codes, errno) for errors when exceptions cannot be used (see Item 63), and for conditions that are not errors. Use other methods, such as graceful or ungraceful termination, when recovery is not required or is not possible."

    (Item 63 basically says, "don't let exceptions propagate beyond the boundaries between your code and the code you don't control.")

    Given that these experts have written at length about error handling, and that they suggest a preference for exceptions when dealing with [non-bug] errors from which you can recover, I think you need to talk more about the kinds of cases where you think exceptions are inappropriate (and give some complete code samples).

    C++ has been accused of containing some useless features, but I don't think anyone of note has said that about exceptions.

    1. Re:"Don't use exceptions" ... huh? by TemporalBeing · · Score: 1
      Perhaps I misunderstood, but it seems that you're advocating the use of error codes instead of exception throwing/catching. Quoth Herb Sutter and Andrei Alexandrescu (C++ Coding Standards, item 74): "Report errors at the point they are detected and identified as errors. Handle or translate each error at the nearest level that can do it correctly." And then there's item 72, which is pretty lengthy and contains lots of references: "Prefer to use exceptions to report errors. "Summary "Prefer using exceptions over error codes to report errors. Use status codes (e.g., return codes, errno) for errors when exceptions cannot be used (see Item 63), and for conditions that are not errors. Use other methods, such as graceful or ungraceful termination, when recovery is not required or is not possible." (Item 63 basically says, "don't let exceptions propagate beyond the boundaries between your code and the code you don't control.") Given that these experts have written at length about error handling, and that they suggest a preference for exceptions when dealing with [non-bug] errors from which you can recover, I think you need to talk more about the kinds of cases where you think exceptions are inappropriate (and give some complete code samples). C++ has been accused of containing some useless features, but I don't think anyone of note has said that about exceptions.


      It's rather the other way around - and I don't by any means advocate using a global errno variable. Rather - each object should have a state within itself, retrievable by a function like Get_Error_Code(), with an associated string retrievable via a function like Get_Error_String(Error Code #). Nothing global about it, and the caller should be checking for error codes when there's an error, and then handle and clear it before continuing; though error codes could be set up to add to each other (e.g an error occurs and there's already an existing error, and a different error code can signify both); however, it would be best if a function didn't work if an error existed (unless it could clear that error).

      Exceptions, by contrast, just encourage lazy error handling and are (IMHO) crap that should not be used unless absolutely necessary. For example, I'm writing a set of API's. The first few sets are not allowed to use exceptions at all and will be the underlying set for any further API's. One of the last sets, while it will continue to support error codes the same way, will have to (because it's an API) support exceptions so that users in an environment that uses exceptions (for whatever reason) can use the API without having to change their program's error handling system. However, those programmers will likely not handle it at the closest level where something could actually be done (if anything at all), and instead just let the error fall out to somewhere else in the system that has no clue about the original object that generated the exception, nor any manner to be able to handle it.

      Perhaps, (and this is just a guess) what you are writing complements what I am saying in some manner (not sure); however, it is not by exception (no pun intended) that the "status codes" (your terminology) should be used, rather it is by exception that exceptions should be used.
      --
      Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
    2. Re:"Don't use exceptions" ... huh? by Anonymous Coward · · Score: 0

      each and every object has an internal error state?

      sorry, but that's just a totally crap way to code, even for 6 sigma or lots of nines nobody decent does that.

      you clearly don't want anybody to use your APIs. if you do, I suggest you read a few books. GetErrorCode() is just not going to fly further than the wastebin.

    3. Re:"Don't use exceptions" ... huh? by neutralstone · · Score: 1

      ["Status code" is not a term I invented.  Note that the term is used in a quoted region.  Again, see Sutter & Alexandrescu.]

      To cut a long discussion short:  I think you should brush up on some of the modern literature on the subject.  Even if you don't agree with it, you would at least be better able to explain why you think the experts have it wrong.  Again, see Sutter & Alexandrescu.  See also Stroustrup, writings by David Abrahams on exception safety, and basically every C++ author who was ever given any credit by the community.  I don't think any of them referred to the use of exceptions as the lazy person's weak substitute for good error handling; and they refer to exceptions (when discussing non-bug errors) as the first consideration, not the last resort.  And they give plenty of compelling reasons for their recommendation, whereas you've given one *weak* reason ("it encourages lazy error handling").  So please forgive me, but I cannot take your opinion seriously just yet.

      You're right in thinking that exceptions should not propagate from library code to client code though -- in fact, that's generally recommended practice -- see my earlier post.  But it's also generally accepted to use exceptions *within* the library code, so long as it doesn't spill over into the space of the library user.

    4. Re:"Don't use exceptions" ... huh? by TemporalBeing · · Score: 1

      You're right in thinking that exceptions should not propagate from library code to client code though -- in fact, that's generally recommended practice -- see my earlier post. But it's also generally accepted to use exceptions *within* the library code, so long as it doesn't spill over into the space of the library user.

      Be consistent inside and outside the program or library. Leave not possibility for a spill-over to occur. That's not a weak reason by any means, nor is it a weak reason that it would "encourage lazy error handling".

      I don't think any of them referred to the use of exceptions as the lazy person's weak substitute for good error handling; and they refer to exceptions (when discussing non-bug errors) as the first consideration, not the last resort.

      They may do just that, but does that make them right? No. If they jumped off a bridge, would you? Now, while Stroustrup may have written the original C++ language; that does not mean he's right about everything since.

      Notably, C++ is a decent language.

      --
      Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
    5. Re:"Don't use exceptions" ... huh? by neutralstone · · Score: 1

      "does that make them right? No. If they jumped off a bridge, would you? "

      I'm not following the advice blindly.   They present compelling arguments, and you (so far) don't.  It doesn't make sense for me to re-state their arguments here, so I'm suggesting that you make yourself familiar with those arguments before you attack the conclusion of those arguments.

  149. Please reconsider C++ by GWBasic · · Score: 1
    It's a myth that you need to write in a language like C++ in order to have fast performence on modern computing. Just like C/C++ supplanted assembly programming in the 80s and 90s, managed environments are quickly replacing C++.

    Please reconsider the C++ requirement. Managed environments like Java and .Net aren't slow, and can call existing C++ libraries. You can even compile Java / .Net so that it runs as fast as C++. Also, don't forget that it's cheaper to buy a faster computer then to write a faster program.

  150. Fight for Software Quality Engineers! by FooManChu · · Score: 1

    Don't make the mistake of putting all the testing and verifying on the developers. Nobody's perfect. Even experienced developers who practice Test Driven Development (TDD) will release software with the most obvious bugs. The fact is, the person writing the code is the worst person who should test it. The developer may have made assumptions that certain algorithm work without actually testing it due to time constraints or worse ego. If you had a good software quality department, they can come up with a thorough test plan and focus on testing the corner cases that would cause instability.

  151. "4. Don't trust that system calls succeed" by neutralstone · · Score: 1

    Ok, but note that some C++ Standard Library functions will throw if they fail.  So when you call these functions, you have to think about exception safety, but you can also assume that they have succeeded on the lines that immediately follow the call.

    (Implementations vary though, so you'll need to check up on this for your compiler.  E.g., with some older compilers, operator new returns NULL upon failure, whereas the Standard says it must throw.)

    1. Re:"4. Don't trust that system calls succeed" by TemporalBeing · · Score: 1
      Ok, but note that some C++ Standard Library functions will throw if they fail. So when you call these functions, you have to think about exception safety, but you can also assume that they have succeeded on the lines that immediately follow the call. (Implementations vary though, so you'll need to check up on this for your compiler. E.g., with some older compilers, operator new returns NULL upon failure, whereas the Standard says it must throw.)


      You still have to, in either case, handle the error and do so without assuming it succeeded. One program I inherited, the programmer assumed every memory allocation completed successfully. Fine under most circumstances, but absolutely horendous if the environment (for whatever reason) becomes overburden and memory becomes extremely scarce (a run away program, or failing RAM). If the call does something (like throw an exception), then use the appropriate means to catch the error and handle it; but don't continue the crappy error methodology just because it did.
      --
      Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
  152. Recoverability by marko123 · · Score: 3, Insightful

    Rather than investing too much time and effort in creating a complicated crash-free program, just make sure your application can recover from a crash, and then use a process management application that restarts the program on it's node when it is detected to not be running properly.

    It's simple to write a 100% correct program that checks the health of your main application, and restart it when it isn't responding.

    --
    http://pcblues.com - Digits and Wood
  153. Your biggest problem will be multiple nodes by carlpny · · Score: 1

    You mentioned possibly running this in parallel. If you're going to have bugs, it will be there. Especially if you want to have this be cross-platform, abstract out your inter-node communication so that you have a choice for what method (ie MPI, raw sockets, etc) you're using to communicate between computers, and put the network error detection and revival code in there. Design the program as you go with parallel execution in mind to save pain later. Sadly, this all is not a simple problem.

  154. On Garbage Collection and Stability by CharonX · · Score: 3, Insightful

    I partially agree.
    If your code is unstable in a way that memory leaks and segmentation faults are not only a "remote possibility" but a - even if only rarely - reoccuring event, then any safeguards you implement won't be overly sucessfull, unless you fix the code that causes the errors first. (Disclaimer: There is no perfect code. Even if there were no bugs in the code, the program has still the "remote possibility" to crash due to errors in the hardware / OS)

    That said, garbage collection or not is a different discussion. Some say it is bad and breed lazy programmers, while others argue (I amongst them) that it is a terrific tool for designers, since it almost eliminates the occurance of memory leaks (unless you do some really bad programming) and it might even speed up your program

    --
    +++ MELON MELON MELON +++ Out of Cheese Error +++ redo from start +++
    1. Re:On Garbage Collection and Stability by dogfull · · Score: 1

      Beard.
      There are certain groups of applications in which it is virtually impossible to assure that no segfaults will ever happen. Dynamicly typed interpreters, for example. The solution is not to evade them, rather to capture them, give an error, and continue.

    2. Re:On Garbage Collection and Stability by dkf · · Score: 1

      Recovery from a memory fault can be incredibly difficult, since you don't know what else got smashed before the fault (usually nothing, but not always). On the other hand, interpreters can have much higher crash resilience than compiled languages simply because their code is relatively dense and the number of places that need to be audited is smaller. (Well, comparatively.)

      Speaking personally, I take it as close to a personal insult when my code crashes for any reason at all. My aim is that all faults should be trapped/trappable faults, though admittedly that's not always possible (memory shortage can be awkward for example, because it's sometimes hard to predict how much memory would be needed to execute a suitable recovery strategy...)

      --
      "Little does he know, but there is no 'I' in 'Idiot'!"
    3. Re:On Garbage Collection and Stability by gbjbaanb · · Score: 1

      I have to say that a bad program will still leak memory, even in a GC environment. All you need to do is allocate objects in a container, the root of which is always kept live. One could say that this is not a memory leak i suppose, but I think that that's just hiding behind words.

      In my experience, this kind of leak is the majority of problems, in a loop its quite easy to see where something is allocated, and you've forgotten to free it, and so its easy to fix that bug. With a container where you forget to remove the object, its not so obvious.

    4. Re:On Garbage Collection and Stability by Anonymous Coward · · Score: 0

      The problem with GC is that heap memory is only one kind of resource, and real-world programs have lots of different resources. A programmer that can't match up the allocations and deallocations in his program to avoid memory leaks is also unable to match up the semaphore p's and v's, or the file locks, or the active/standby table swaps, or what have you. Introducing a GC to "solve" (cover up) the heap allocation problems does nothing to solve the other resource allocation problems. If the programmer cannot demonstrate analytically (not by testing) that all allocated resources are freed, then the system is headed for trouble, GC or not.

      Particularly for efficient, embedded, systems, it's crucial to be able to release a resource immediately when it is no longer needed, rather than waiting around from some generalized GC to decide to finalize a resource and allow the system to continue running.

      The C++ RAII style is a very neat and tidy way to code resource allocation critical regions; try/catch/finally and delayed GC destroys that paradigm, and makes the equivalent manual code more verbose, harder to write and thus buggier.

  155. You are correct. by Anonymous Coward · · Score: 0

    Of course it's more of a question of most C/C++ compilers lacking an option "force-checking-of-all-return-values" than anything else. Exceptions have their own set of problems, though. Try googling for "strong exception guarantee".

  156. "5. Be explicit about everything in your code." by neutralstone · · Score: 1

    It's good to be explicit about some things, but don't be inane.

    For example, "int" is *always* "signed int" -- this is in the language definitions.  So it's a waste of time to spell it out.  Note the signed-ness of plain 'char' is implementation defined, so you could legitimately be explicit about that.  But note again that a lot of Standard Library functions use plain 'char', so you have to be careful that your explicitness doesn't break things.

    It does help to be explicit about, say, constructors (which is why the creators of C++ added a keyword just for that purpose).  E.g.:

    struct A
        {
        explicit A();
        explicit A( const A& );
        explicit A( int );
        };

    In short:  be as explicit as you need to be (such that any human reader could draw the same conclusions), but no more.  E.g, the parentheses in "a + (b * c)" are superfluous because everyone knows (or can quickly find out) that binary '*' has higher precedence.  But then again, with lots of sub-expressions, it can help to add parentheses, line breaks, and indentation at certain points to ease readability.  There's no hard rule for it; you just have to feel things out.

    1. Re:"5. Be explicit about everything in your code." by TemporalBeing · · Score: 1

      *It's good to be explicit about some things, but don't be inane.*

      Actually, it's good to be inane. Why? It'll help you debug it that much faster. Who cares if it takes 2 more seconds to type it in, if it saves you 5 minutes in debugging?!!!

      *For example, "int" is *always* "signed int" -- this is in the language definitions.  So it's a waste of time to spell it out.  Note the signed-ness of plain 'char' is implementation defined, so you could legitimately be explicit about that.  But note again that a lot of Standard Library functions use plain 'char', so you have to be careful that your explicitness doesn't break things.*

      The standard *may* say that, but don't trust it. It could change in 5 years, and then what? You're code would be broken. Is that change likely? No. But don't trust it. Don't trust your own code. Don't trust that a compiler will follow the standards. The more you don't trust it, the more you are likely to have a program that is rock solid.

      That is not to say that you should do something like following:

      X = B;
      if (X == B)
         {
         }
      else
         {
         /* Fail */
         }

      That's inane. But it is perfectly valid to be explicit about things like "signed int". It'll help you read the code, and it'll help you debug the code. And if you do have a problem calling something because it wants an "int" versus a "signed int" than I would suggest writing a wrapper that would do nothing more (could even be inline) than perform the necessary type-casts. (Typcasting yourself could be done too, but using a wrapper would be better.)

      Additionally, if the compiler knows that an "int" is a "signed int", then it should do the change for you automatically - if it is a good compiler. But again, you don't necessarily need to trust it to do so; but I would say this is one case where you ought to be able to trust to to make that conversion for you *if* that's what the standard says and it complies with the standard.

      *In short:  be as explicit as you need to be (such that any human reader could draw the same conclusions), but no more.  E.g, the parentheses in "a + (b * c)" are superfluous because everyone knows (or can quickly find out) that binary '*' has higher precedence.  But then again, with lots of sub-expressions, it can help to add parentheses, line breaks, and indentation at certain points to ease readability.  There's no hard rule for it; you just have to feel things out.*

      Be explicit about your parenthese and everything else - it'll help you debug it, and ensure that the compiler understands you correctly. It would also save your butt if whoever wrote the compiler decided to change to a different style of precedence or association (prefix/postfix, etc.). Don't trust 'em - and don't trust yourself to get it right every time, or read it correctly everytime. Like I said above, it'll may take you an extra 2 seconds to write, but it'll likely save you 5 minutes or more in debugging time.

      *It does help to be explicit about, say, constructors (which is why the creators of C++ added a keyword just for that purpose)*

      I'm not saying anything about keywords in regards to being explicit. I'm simply saying that you be as clear in your code as possible - don't assume that another programmer will assume anything. Be explicit about what your code is and does. Do the same in your commenting.

      --
      Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
    2. Re:"5. Be explicit about everything in your code." by neutralstone · · Score: 1

      Re: ISO comittees changing meaning of 'int' from 'signed int' to 'implementation-defined'.

      Not only is it "not likely"; it's "not-bloodly-likely", and it's "not-gonna-happen-in-this-universe--ever".  This is a rule that held in K&R C, or, as some people like to call it, "Nixon-administration-C".  It's one of those really, really old rules -- as old as C itself -- that all compiler vendors have always followed and will not dream of breaking unless we're talking about some experimental language that is not C or C++.

      'signed int' is 'int'.  They are different syntactic representations for the exact same internal type.  No meaningful argument about this ever existed or will ever exist.

      Same goes for operator precedence.  The precedence rules have always just "been", and they have been followed consistently in every implementation of C and C++.  There are other points of language interpretation that vary from compiler to compiler, but those points are overwhelmingly related to non-C, C++ features.  I defy you to point out *one* implementation that proves me wrong.

      Re: the 'explicit' keyword:  Sorry, I didn't really mean to draw attention to the keyword itself; just that use of it ensures that you won't be left trying to figure out where all the implicit ctor calls are.

      Re: the being-explicit-to-the-point-of-pointless-redundanc y-will-shorten-debug-times argument:

      Bull. Having a better understanding of the language will shorten debug times. Adding meaningless layers of syntactic redundancy will only hurt the eyes of people who know what they're doing.  If a newbie doesn't understand some nuance of the language, it means he needs to spend some time getting to know the language better, and no amount of adherence to a coding style will acceptably substitute that.

  157. As I have been stating before. by Z00L00K · · Score: 1
    You should try to impose a few rules of coding.
    • Instanciate coding guidelines - code must be easy to read. Minor variation in coding flavour shouldnt be here, merely the large scope.
    • Avoid if...else if...else if...else if... - constructs. They are especially hard to follow, and can often be replaced by switch/case-statements.
    • Require large modularization of code. - No function/method should be more than about 40 to 100 lines, the fewer the better, but don't be too rigid here - some functions/methods are better of being straight-on than modularized.
    • Code for each case-statement in a switch should be a call to a method/function that encapsulates actions and declarations. (not always possible, but if the code exceeds 4-5 lines a function/method should be considered).
    • Don't nest a switch/case inside a switch/case - do the nested switch in a called function/method.
    • All code must be reviewed.
    • Test cases for each module, which requires writing a bunch f test code that can be used for regression testing changes.
    • Don't allow compiler warnings. (-Wall shall be used if using gcc, possibly also other options)
    • Declare your own types to manage code neatly.
    • It's better to write code cleanly than to write it in the most compact manner unless it's a real performance issue.
    • Document each module to describe why it is and what it is doing.
    • Place each class in it's own file - like Java.
    • Be sure to keep as much as possibly 'private' and only relax to 'protected' or 'public' when needed.
    • Variables in classes should have get/set methods and shouldn't be accessed directly unless there is a performance issue. Set methods can then be able to validate indata and reject or throw an exception on bad data.
    • If something can't be resloved without a compiler warning - think again and if still not possible - document that reason before the code review.
    • Run the code under analysis of leak and memory access testing software like Valgrind and/or PurifyPlus. Preferrably both during unit testing and system testing.
    • Be paranoid. Check for 'null' results and do detailed try/catch blocks instead of a try/catch over a large block. Using detailed checks allows you to take appropriate action on detail errors.
    • Instaciate an extensive beta-testing program.
    • Inline-declare function/methods that are broken out if they should be inline with the code for performance reasons.
    Notice that PurifyPlus is a package that allows you not only to detect memory leaks and invalid memory accesses, but is also able to do performance analysis of the code with Quantify as well as checking that you actually have tested all code by the component PureCoverage. This allows you to be able to focus your work on improving application performance on the places where it really matters.

    For code written in C you can use Splint

    --
    If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
  158. Consider Ada by kafka.fr · · Score: 2, Informative

    Using the good-old Ada programming language (for which a new standard should be issued this year), you can go closer to what you're looking for (though I'm not sure your goal is realistic).

    Here's a pointer to the new standard : http://adaic.org/standards/05rm/html/RM-TTL.html

    With Ada:

    • you can call externally-defined C/C++ functions (see annexe B);
    • you get quite advanced runtime-checks;
    • you have plenty of exceptions to use to catch errors (see sections 11 and section Q.4);
    • you have tasking (more or less threading) implemented inside the language (see section 9);
    • a specialized annexe is targetted toward distributed system (annexe E);
    • specialized annexes for high-integrity systems (annexe H) and real-time systems (annexe D);
    • ...and more, much more.

    It probably won't solve every of your problems, but it might help.

    For a free, quite strong Ada compiler, have a look at https://libre2.adacore.com/ (it's based on GCC).

    Oh yes, Ada is a statically, strongly, strictly typed language (e.g. the compiler won't let you assign an integer to a float variable). My opinion is that it's a Good Thing for critical programs. Useless to restart a "type war" on this subject ;-)

    Good luck.

    1. Re: Consider Ada by Black+Parrot · · Score: 2, Informative

      > Oh yes, Ada is a statically, strongly, strictly typed language (e.g. the compiler won't let you assign an integer to a float variable). My opinion is that it's a Good Thing for critical programs.

      Yes, it's very frustrating when you first start using it because it makes you say what you mean and mean what you say, but once you get over that you find yourself writing programs where certain kinds of bugs simply never happen.

      The strong typing (no, strong, not the fluff some other languages call "strong") and run-time checks work to move error-discovery forward. That is, you find stuff a compile time that most languages leave you to find at run time, and you find stuff at run time that most languages leave you to (hopefully) notice that you're getting incorrect outputs.

      --
      Sheesh, evil *and* a jerk. -- Jade
  159. "6. Be explicit in your logic" by neutralstone · · Score: 1

    Note that because C++ allows automatic destruction, having a single exit point explicitly represented in the program source code is not terribly important, and sticking hard-and-fast to this rule may lead to some unnecessary performance hits on account of extra calls to class assignment operators, extra class object temporaries, etc.

    An explicit "single exit" rule makes more sense in a language like C, where there is no language feature that enables simple automatic clean-up.

    1. Re:"6. Be explicit in your logic" by Anonymous Coward · · Score: 0

      automatic cleanup, yeah, only for objects on the stack, oh wait C++ is exactly like C!

      (not that I would ever have more than a few news hanging around in my code that aren't in constructors. it's amazing how few you can away with. standard good practice - every time you write 'new' think about how you can not do so, same with type casts. you'll be better for it.)

    2. Re:"6. Be explicit in your logic" by TemporalBeing · · Score: 1

      Note that because C++ allows automatic destruction, having a single exit point explicitly represented in the program source code is not terribly important, and sticking hard-and-fast to this rule may lead to some unnecessary performance hits on account of extra calls to class assignment operators, extra class object temporaries, etc. An explicit "single exit" rule makes more sense in a language like C, where there is no language feature that enables simple automatic clean-up.

      Try maintaining a program in any language that does that - it's nearly impossible. Don't count on automatic destruction. Even in C++ if you allocate memory, it won't necessarily delete it at the end. (For example object* A = new object; The new object won't be deleted automatically when the function exits.) And garbage collecting is not an answer either - it may save your butt from memory leaks, but the memory leaks still exist; and it will (a) add overhead, (b) slow down your program, and (c) won't clean them up immediately - it waits until its next scheduled cycle.

      Single-Entry-Single-Exit is one of the best programming practices a programmer can have. There are few exceptions to not using it - like certain chunks of code deep inside an OS kernel that just have to work a specific way that doesn't allow for it.

      --
      Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
    3. Re:"6. Be explicit in your logic" by TemporalBeing · · Score: 1

      *(not that I would ever have more than a few news hanging around in my code that aren't in constructors. it's amazing how few you can away with. standard good practice - every time you write 'new' think about how you can not do so, same with type casts. you'll be better for it.)*

      Not always possible, but a good idea. For example, you shouldn't be doing:

      int* num1 = new int;
      int* num2 = new int;
      ...
      delete num1;
      delete num2;

      in the same function. But there will be times (like dynamic arrays) where you just can't get by without it. (And no, a vector STL or anything similar is not the answer either.)

      Rather, just be responsible and make sure that your program's architecture allows for a single point of creation and a single point of deletion for objects that are necessary to be created in one place and handed around throughout the life of a program being different parts of the program.

      For example, an array of buffers can not always be defined statically - and likely, in most situations needs to be dynamic. For example, try getting a listing of network interfaces from Windows. The first call will tell you how much memory need - for example, if there are 2 interfaces or 1. You can not hard code a static array there because you won't know how many there will really be - there could be 1000 - and the memory cost would be too much to hard code it, not to mention that it would not allow your program to be flexible.

      There are trade offs - and they need to be decided & justified. Don't allocate something on the heap just because you can. Don't do it on the stack either just because you can. Make a valid choice based on why the memory is being allocated, and then back it up by providing the facilities within your program to properly clean it up. (e.g. a buffer pool that is in charge of allocating and destroying any buffers for a specific part of your program's algorithm).

      --
      Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
    4. Re:"6. Be explicit in your logic" by neutralstone · · Score: 1

      I *do* maintain a program without a strict OEOE rule, and it *is* quite feasible; we've been doing it for many, many years now.  There are several places where we have things set up OEOE-style because it helps the algorithm, but we really don't need it *everywhere*.  There are lots of functions where OEOE would be an imposition that does not arise from any real need, but from blind adherence to coding "standards".

      We write source code to solve problems in a way that other programmers can understand.  If there is a function where OEOE doesn't improve a reader's understanding, why use it?

      And yes, I'm quite aware that dynamically allocated objects will not be automatically destroyed upon exiting from the scope of their allocation, because such objects don't have a "scope".  That's why you *give* them a scope by using smart pointers.

    5. Re:"6. Be explicit in your logic" by TemporalBeing · · Score: 1

      And yes, I'm quite aware that dynamically allocated objects will not be automatically destroyed upon exiting from the scope of their allocation, because such objects don't have a "scope". That's why you *give* them a scope by using smart pointers.

      "Smart Pointers" are not a solution - just a bandaid. The solution is teaching programmers how to actually program correctly, part of which is managing resources. If you can't do that, then you don't belong teaching programmers how to program, and if a programmer can't do that then they don't belong programming. Pure and simple.

      I *do* maintain a program without a strict OEOE rule, and it *is* quite feasible; we've been doing it for many, many years now.

      What is your turnover rate of programmers working on the project? OEOE (Open Entry/Open Exit)may be useful for certain kinds of assembly programs, but in general across most any program or programming language it is complete crap, and SESE (Single Entry/Single Exit) should be adhered to. More specifically, OEOE may be good for parts of an OS kernel or driver, but for any application or non-hardware interfacing code in a kernel, SESE is best.

      There are lots of functions where OEOE would be an imposition that does not arise from any real need, but from blind adherence to coding "standards".

      The "real need" is doing it right, and doing it in a way that results in correct results every time using a consistent, efficient, and well thought out style. OEOE will not achieve this, and will cost you time and money in maintenance that SESE won't. Try tracking a resource that was allocated in one place, and dellocated somewhere else. Or try determining how many different places a program terminates from. With SESE that's very simple - 1. With OEOE, good luck.

      SESE is best programming practice. It is also (in good programming circles) the rule, not the exception. OEOE, however, is the exception.

      --
      Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
  160. use static and dynamic analysis tools by Anonymous Coward · · Score: 0

    Tools such as purify,valgrind (dynamic analysis) and other tools such as Coverity (static analysis) should be used along with all the other methods.

  161. Move #10 up to #0 by neutralstone · · Score: 1

    I agree with item 10, but it should be stated earlier and more often.  Bugs in the analysis of requirements and in the design can literally cost years of lost time -- and I'm not counting man-years.  If the design is correct, then so many other decisions just naturally fall into place.  If it's flawed, you'll spend a lot more time than expected on development.  If it's deeply incorrect, you'll be in a world of hurt.

  162. it's all about synchronization by Al+Clocker · · Score: 1

    If you're a reasonably competent programmer, you won't have crashing issues with pointers in C++. They're not that hard to deal with, unless you're doing some weird kung-fu with templates or function pointers. Even then, crash-avoidance is not the difficult part. In your case that hard part is going to be synchronization between different things that are running concurrently, and those problems have nothing to do with the language you use. In fact, since C++ is a system programming language you probably have more options available to help with synchronization than you would in other languages.

  163. I built something just like this... by Anonymous Coward · · Score: 0

    I already (successfully) built a project that sounds just like this. I currently have a 500Mb database with 2500 data sets in which the clients are adding another 0.5Mb/day to. In my system, it's not so much about the size of the databse but rather the time needed to calculate the data.

    Here's what I did:

    1) GUI

    Server side web interface (python, apache, mysql, php, svg)

    2) Core data structures, a persistent object storage mechanism
    MySQL + phpMyAdmin

    3) a distributed communication module and several core algorithms.

    Python + urllib (communicates with the server through cgi). I also use the pysco python jit compiler for speed.

    If your algos are complex enough you could also look into Numerical Python. Or, If python is too slow, you can write just your algos in c/c++ as a python extension module.

    The remote clients connect through server side python cgi scripts on a SSL connection. I "pickle" and compress the datasets in both directions for transport across the network.

    If you need a client gui then look into WxPython.

    My System works like a champ! And the simple reason is that I intentionaly sought out mauture proven tools that when combined left me with only the task of glueing them together and adding the application specific code. The result -- both the client and the server are naturaly portable across Linux, Windows and (nativly :) OSX.

  164. Someone has to say it... by piotrr · · Score: 1

    ...do your own homework!

    --
    / Per
  165. Nit about (1) by neutralstone · · Score: 1

    Note that the run-time cost of copying a class object may be such that it makes more sense to pass a copy instead of a const ref (and incur the cost of constantly "dereferencing" that reference).

  166. One possible design by heli_flyer · · Score: 1

    It sounds like all your modules need to be separate processes, and then you need a central module which handles restarting crashed modules and handles and logs all communications between processes. When a crashed module restarts, it needs to query the central module to retrieve a log of the prior messages to reconstruct its state. This obviously requires careful design of the protocols between the modules - they protocols need to be either non-state-dependent or you need to send a full state dump periodically to allow the central module to dump old state info.

  167. Design from failure... by Anonymous Coward · · Score: 0

    Oh, come on, stop making yourself miserable !

  168. Safe Pointers by S.Gleissner · · Score: 1

    About 10 years ago i had a project on university, where i have implemented a "safe pointer" C++ template. The quite complex program (no GUI, portable) was for optimisations, it generated and deleted a lot of C++ objects.

    Every class in the project was derived from one base class, which enabled the ability to be a "safe object". All Pointers were in fact objects, generated by the template and the class the pointer pointed to. New objects were normally generated with "new", but there were no "delete" commands. The objects were deleted automaticaly when the safe pointers were deleted or overwritten. When more than one safe pointer was pointing to an object, the object was deleted when the last safe pointer was deleted or overwritten.

    Based on this safe pointers i wrote some list and tree classes. I never had any problems with memory leaks or uninitialized pointers. Yes, i think it is possible to write big and safe C++ programs, as long as you control the pointer problem.

  169. Need, no, but it's still a good idea. by warrax_666 · · Score: 1

    It's simply impossible to forget to delete with a shared_ptr... no matter how simple you make it to remember, you WILL forget to delete one of your pointers at some point (or several points). Any time you need to manually insert code to do something you're just increasing the number of things that can go wrong, better just to be safe and always use smart pointers.

    --
    HAND.
    1. Re:Need, no, but it's still a good idea. by Brandybuck · · Score: 1

      Why is there no similar paranoia over files? If I am supposed to completely abandon C/C++ because pointers aren't automatically deleted for me, then why should I be moving to a language that won't also automatically close my open files? What's the difference?

      --
      Don't blame me, I didn't vote for either of them!
    2. Re:Need, no, but it's still a good idea. by Anonymous Coward · · Score: 0

      Well, that same mechanism should be used with files too.

      RAII all the way :)

  170. Take a look to Postfix by Anonymous Coward · · Score: 0

    Take a look how Postfix is programmed http://www.postfix.org/OVERVIEW.html

  171. Let me code it ... by Anonymous Coward · · Score: 0

    While there's more to this, what strategies should a developer take to insure that the resulting program is as crash-free as possible?

    Let me code it ...

  172. Re #1: by warrax_666 · · Score: 1

    Unfortunately using refs can obscure the meaning of your code, specifically when used for "out" parameters -- ignoring the obvious const-ref usage. I've found that always using pointers for "out" parameters helps make it more obvious at the call site that something is being altered by a function/method call.

    --
    HAND.
  173. Avoiding dangerous practices by MORB · · Score: 1

    Defensive programming might be necessary for the kind of stuff you want to make.
    However, there are also a lot of good practices when it comes to coding in C++ that will help you have better, more trustworthy code. Sorry in advance if these seem obvious.
    It is of course merely my opinion, and some of these advice may be wrong or horribly wrong.

    1. If you need to do something that the standard C++ library can do, use the standard library. Don't implement your own containers unless you really, really need to.

    2. Never use the stuff from the standard library that were inherited from C. Examples:
    Use stringstream instead of sprintf.
    Use file streams instead of fopen and the like.
    Never use any XXXcpy function (memcpy, strcpy, etc.). If you need to do it, think twice, and then think again. It shouldn't be necessary in most cases.

    3. Never do pSomething = new Someclass if you need the instance only in the scope where it is defined.
    Use Someclass Something, and you won't need to put a delete pSomething in every place where you can leave the function.

    4. Pointer arithmetic is bad. You should almost never need to add an integer to a pointer, or to take the difference between two pointers.

    5. Casts are dangerous. Always use C++ style casts, like static_cast. C style cast should be avoided. reinterpret_cast or const_cast should be a very, very rare occurence, so think twice if you think you need one.

    6. Respect constness everywhere it is needed. And respect it properly, not by using mutable or const_cast liberally (unlike what some people did in the codebase I'm maintaining at work :/)

    7. If you have a boolean, use bool. Not int or whatever else.

    8. Use smart pointers. With reference counting for objects with shared ownership, or just to automatically delete stuff that goes out of scope.
    Then you can write SmartPointer = new blabla and don't need to explicitely delete. This simplifies the code in functions because you don't have to delete in every place you leave the function, and in classes because you cannot forget to add the delete in the destructor.
    And it's the only proper way to work with exceptions.
    If you want to be strict, block the ampersand operator in classes that you want people to access only through smart pointers, and also forbid constructing or setting a smart pointer from a reference (to prevent errors like making a smart pointer point to an instance on the stack)

    9. Beware of large classes and large functions. If you want to be able to trust that the code works, you need classes and functions that perform a single, well-defined task. You can then easily verify that they do what they're supposed to do and not more or less.
    When you have a class or function with a vague name, a vague purpose and that spans pages of code, you cannot easily audit it to check that it does what it's supposed to do.

  174. Attitude by DCFC · · Score: 1

    To make s/w reliable you have to assume that it isn't. Although NASA lost the plot decades ago, it's worth looking at how IBM engineers built systems that could survive the failures of these chimps. IBMers assumed that everything could go wrong. There was great pride in the team when they found a stupidly obscure and massively unlikely bug. There was no notion of "having to decide whether you were an engineer or a manager". IBM stuff managed to survive things like motherboards being melted in flight with microgee solder balls shorting out the rest of the system. Even in Challenger the IT was working as it hit the water on the way down. That culture is far more important than any single technique. Implicit is the notion that no one can really check their own work. You need someone who takes a positive joy in pointing out your errors. That needs to be backed up by managment, who must not only avoid trating bug finders as trouble makers, but positively reward them, and yes that means cash. I think we can already see why so much commercial s/w has stupid levels of bugs... If you're serios then I'd suggesting voting as an architecture Multiple modules to take decisions. To do this properly, each needs to have different code. The gold standard is separate code, each in a different language written by a different programmer. The mulitple language precept is because two programmers in (say) C++ may actually make the same error from the same specification. A classic example is "between one and ten items". Different people may interprest that as including 1 and 10, or excluding them, or in the case of some C++ developers 0..9 VB programmers "know" that Dim q(10) actually has 11 elements in it. Voting puts a bound on the effect of a failure.

    --
    Dominic Connor,Quant Headhunter
  175. Exception Handling by Anonymous Coward · · Score: 0

    It's too bad that none of the other posts I read here contained any information. That said, for my $0.02, exception-handling is one of the best mechanisms you can use to make your system reliable.

    Good luck....

  176. Practical Advice by ralphclark · · Score: 1

    I'm probably not on the same level as some of the people here, but here are a few strategies I've learned along the way:

    1. Exception handlers - bracket every functional unit with exception handlers to catch any situation that hasn't been provided for explicitly. It's worthwhile thinking hard about what to do when an exception is caught though. For the sake of code maintainability you need to figure these in as a fundamental part of the design and think in terms of a hierarchy of handlers where at each point you make a decision whether to handle locally or pass the problem back up the chain.

    2. Safe memory allocation - avoid allocating "big enough" static structures - take the GNU coding guidelines' advice and avoid arbitrary constants. And use a decent third party safe malloc() implementation.

    3. Bounds checking. You should do your own bounds checking to preserve the logical integrity of your execution path, but ideally you should link in with a well proven third party bounds checking library as well.

    4. Waypoints - there might be places in the code where you can save valid partial results to disk in order to minimize reprocessing when a thread has to be restarted after an exception handler has passed control back to a caller some way up the line.

    All I can think of right now...

  177. boo by Anonymous Coward · · Score: 0

    Never took that serious, but /. is really a "do my homework for me" place now, isn't it?

  178. TRUCO (*) by hummassa · · Score: 1

    (*) == I call BS.
    Do you all really think putting a (possibly buggy [MS]) virtual machine in the game will make his app more stable? OMFG...

    --
    It's better to be the foot on the boot than the face on the pavement. ~~ tkx Kadin2048
  179. Nooo!!! No separately restartable modules!! by Handyman · · Score: 2, Interesting

    In my experience decoupling and automatic restarting is a recipe for failure. You set yourself up for all sorts of race conditions. For instance, if a module is unresponsive for a while but not crashing, do you restart it? And if you do, what if the original module finishes its grand execution plan and comes back up after a minute?

    No, I'd go for:
    * A "monolithic" application with module separation provided by OO design. At least you know that either your whole application is there, or it isn't. No inconsistencies between modules because of individual module re-starts, and if the app breaks, restart the whole thing. Starting the app is the code path you've tested, restarting separate modules usually isn't (and even if it were, there's usually 2^27324 different situations to test, i.e., all possible combinations of modules failing in any sort of way).
    * Use smart pointers exclusively, preferably Boost's shared_ptr. Use weak pointers (Boost provides an implementation for that as well) to automatically break reference cycles.
    * For error handling, use exception handling exclusively. Incredibly many bugs are caused by ignored return codes.
    * Use "auto" objects for all resources that you acquire and that need to be released at the end of a code section. Cleanup that doesn't happen when a code path encounters an exception can cause resource leakage, instability and hangups (locks, anyone?). In my programming practice, when I allocate a resource (memory, refcount, open/close a recordset, etc.), I always wrap it in an auto object immediately, so that I can forget about managing it through all the code paths that follow.
    * Use the correctness features that the language provides: write const-correct code from the start.
    * Use automated testing right from the start, both unit testing and integration testing. If you don't do this, you will be forever tied to whatever bad design decisions you make in the first months of the project. Automated testing allows you to always make large implementation changes, giving you confidence that it will not break existing behaviour.

  180. Test-driven development by StrawberryFrog · · Score: 1

    what strategies should a developer take to insure that the resulting program is as crash-free as possible?

    Simple, easy answer: unit test it as much as possible, then tinker with the design to make more unit tests posible.

    Beyond that, do regular code reviews and get into the habit of programming defensively.

    this applies to any language, not just C++. There's even a port of JUnit to C++ over here

    --

    My Karma: ran over your Dogma
    StrawberryFrog

  181. Obvious ! by Thomas+Miconi · · Score: 5, Funny

    What this guy really needs is the time-tested, tried-and-true Waterfall development process !

    Thomas-

    1. Re:Obvious ! by GroovBird · · Score: 2, Insightful

      Well since the parent is posting a link to a satirical website I wouldn't moderate his post as "informative" but oh well.

  182. Use Z - but don't expect it to be easy by madmarcel · · Score: 1

    Use formal methods, it's what NASA and companies that develop medical software use.

    I'd recommend B or Z.

    There are even methods/software that will help you convert your specification from B/Z to C/C++ code (or other languages).

    (Just a word of warning: This is not going to be easy or fun, but it will make your software robust, and you will catch a lot of errors before you even start coding)

    http://www.zuser.org/z/
    http://czt.sourceforge.net/

    1. Re:Use Z - but don't expect it to be easy by mobileink · · Score: 1
      Absolutely agree! But I quibble about the "easy and fun" part; I find Z to be remarkably clear, simple, and concise, and fun to use, precisely because it helps one to think at a high level of abstraction. Use it a bit and you will see much more clearly the artistry involved in writing texts in formal languages (i.e. programming). It's all about manipulation of form, like any art.

      You can write all the unit and system tests you want, but you'll never get better than "passes the tests we wrote!", so the best you can do is give some sort of vague estimate of the *probability* that the stuff won't crash and is correct. But if you use formal methods like Z you can prove mathematically that your specification is consistent and bug free. (Note: that doesn't mean it models the problem correctly.) Then implement using a functional language like SML or Haskell and you get more provability. Contrary to some assertions on this thread, it is indeed possible to write programs that will never crash - all you have to do is use a good (typed) FP language.

      All the sincere advice about how to code and test bugless code is useful if you have no choice but to work in stone-age conditions. But why not let the computer handle stuff like that? Then you can focus on the real task, which is correctly modeling a real-world problem.

  183. How to get reliable code SEI CMMI Level 5 by elrond2003 · · Score: 1

    Beyond language ,beyond buzzwords, read up on the requirements for SEI CMMI certification. Basically the point is to documanent everything, all procedures, all requirements, all test results, everything. Only once have I had the pelasure of working on such a project, the resulting application is 100% rock solid, and delivered ahead of schedule. (a bit over bifdget however, 2of three is not bad). Going in I would have thought that it would be terrible, but once I realized how nice things were without the usual bickering, I would hesitate to work without the SEI cert. You really don't need level 5, level 3 will suffice, but read all of the requierements and get a good coach to help set things up. It is really worth it. Oh, yes, the app is written in C++ and runs on PPC under PSOS.

    1. Re:How to get reliable code SEI CMMI Level 5 by mkswap-notwar · · Score: 1

      I've worked in two companies so far that have SEI CMM/CMMI certifications, and I'll agree, it works well. I'll also expound on your statement of the resulting application is 100% rock solid, and delivered ahead of schedule. (a bit over bifdget however, 2of three is not bad)

      There's only so much you can control. In building software, management is generally worried about three things: Budget, Schedule, and Quality.

      Your 2 out of 3 is fantasic, and would be for any project. It's when management tries to control all three, and make them all fall in line to perfect expectations, that you have trouble. As soon as you dictate that all three must happen without exceptions, your project is doomed.

      --
      "I reject your reality, and substitute my own!"
  184. Use Haskell? by beelsebob · · Score: 1

    You can link against your C++ libraries using the forgien function interface. Functional programming is extremely efficient for distributed computing (see google). Finally it's a lot easier to write stable code.

  185. Smart pointers and high-level abstractions by djelovic · · Score: 1

    The main difference between C++ and other popular languages these days (other than gross syntax) is C++'s lack of garbage collector. Thus in C++ you can corrupt memory while in other languages you can't.

    Yet we haven't experienced _any_ memory corruption in the medium-scale project we are working on? The trick? We avoid all C-style pointer-based constructs and instead use only higher-level, type-safe abstractions like smart pointers, vectors, strings, etc.

    In the places those aren't available, we build safe constructs on top of the unsafe ones.

    For example, instead of calling pthread_create which passes the parameters to the thread function through a void*, we have 20 createThread template functions that can be used to start a thread function with 0-19 arguments.

    This leaves us with a single avenue for memory corruption: modifying a STL container while it's being iterated through. While it's impossible to prevent those at compile-time, a library like STLPort will catch them at run-time.

    Dejan

    1. Re:Smart pointers and high-level abstractions by Sigma+7 · · Score: 1
      The main difference between C++ and other popular languages these days (other than gross syntax) is C++'s lack of garbage collector. Thus in C++ you can corrupt memory while in other languages you can't.


      A garbage collector protects against the leakage of memory and has nothing to do with what you described. What you wanted is boundry checking and/or a ton of other features designed to prevent a random corruption of memory - and that's already available in the most modern of compilers as an extension.

      For example, instead of calling pthread_create which passes the parameters to the thread function through a void*, we have 20 createThread template functions that can be used to start a thread function with 0-19 arguments.


      If you have to re-implement a generic function 20 times (once for each parameter), then you are doing something wrong - it means you have to implement it again the instant you need an the 21st parameter. C programmers would use the vararg functions, pass an array, or would pass an array of pointers - and it shouldn't be too hard for C++ programmers to do the same in a secure and type-safe method.

      It's either that, or put a wrapper function based around individual start points for threads.

    2. Re:Smart pointers and high-level abstractions by djelovic · · Score: 1

      "A garbage collector protects against the leakage of memory and has nothing to do with what you described."

      Not really. In languages like Java or C# the garbage collector guarantees that a reference will never point to a block that you don't own. You can't construct a reference to memory you don't own, and the memory won't be freed if you own it.

      Also, garbage collectors _do not_ protect against memory leaks. Anybody that has ever programmed a data structure in a garbage collected language will tell you that. You still have to remember to set unused references to null (just like you have to delete them in C++) or you will have leaks.

      "If you have to re-implement a generic function 20 times (once for each parameter), then you are doing something wrong - it means you have to implement it again the instant you need an the 21st parameter. C programmers would use the vararg functions, pass an array, or would pass an array of pointers - and it shouldn't be too hard for C++ programmers to do the same in a secure and type-safe method."

      Actually, I have to implement it once for each parameter _count_, as I said in my post.

      Varargs are out of the question, as they are not statically type safe and a frequent source of memory corruption.

      If you find a way to do it without writing different functions for different argument counts, we'd all like to hear about that.

      You have the podium.

      Dejan

  186. Think about your goals first by thsths · · Score: 1

    > I need to create an ultra-stable, crash-free application in C++.

    First order of the day: think about what this means. You want an ultra-stable application, so you conclude it shouldn't crash. Right. But it also shouldn't get stuck. Or return the wrong data. Or screw up something.

    Once you have a good idea of what you want to avoid, just limit your use of the language features. Afraid of NULL pointers/dangling pointers? Ok, use smart pointers. But check that your smart pointer library is rock solid.

    Afraid of deadlock? No more while loops, for loops only with a maximum loop counter, no more recursion etc. See, it is getting rather tricky.

    In the end, C++ can probably do this if you use the necessary restrictions, but it is not going to be efficient. Using an interpreted language might be the easier option.

    Too slow? Fast, safe and useful, pick two out of three.

  187. Conflicting constraints by Archtech · · Score: 1

    Classically, you cannot optimize two parameters simultaneously. Thus, if reliability and robustness are the most important things, coding in C++ must logically be less important. Even so, of course, there might be no practical alternative. But I don't believe that is so. A lot of the trouble we have with modern software is that the people who produced it did not assign a high enough priority to reliability or security.

    I realise this probably isn't a practical suggestion, but it is at least an existence proof. In the VMS Common Language Environment you can mix languages more or less ad lib. Thus, you could call C++ libraries from a simpler and safer language such as Pascal, Ada, or even Java. (Yes, I know Ada is big and complex, but there is no law that says you have to use all of it. Besides, reliable/secure subsets have been defined for mission-critical or safety-critical applications).

    Can't you do similar mixed-language programming in .NET? The libraries you refer to are presumably fairly robust, so if you write your own code in a safer language you should be OK. Clearly, other parameters such as performance and cost may be affected, but as already stated, you ca't optimize everything.

    --
    I am sure that there are many other solipsists out there.
  188. Some simple rules... Formatted. by Futurepower(R) · · Score: 1
    I wish you would post some more rules like that, or provide links.

    I needed to reformat what you said before I could read it easily:

    I've been out of C++ programming for several years, but I do remember a couple basic rules I followed that saved me from a lot of memory problems and invalid state problems. This may not be the kind of thing you're looking for, but here it goes...

    1) Never allocate memory to a raw pointer. Never. That is, if you allocate memory to something, it better be allocated to a smart pointer like auto_ptr or a reference counting pointer (boost.org at the time had a family of these). The only exception to this rule is in the implementation of the smart pointers themselves. You should be able to find a good number of articles on this.

    2) Always follow the "strong exception safety guarantee". Classes that provide this guarantee promise that they will not change their state if they throw an exception. Again, there are many articles. Here's an example of an assignment operator providing the guarantee (please forgive me if my C++ is not quite right - I'm rusty):
    Whole::operator=(const Whole& that)
    {
    auto_ptr tempPart1 = new Part(that.part1);
    auto_ptr tempPart2 = new Part(that.part2);
    this.part1 = tempPart1;
    this.part2 = tempPart2;
    }
    The example is a class Whole with two dynamically allocated Parts. The assignment operator instead of having two lines of code - i.e. cloning the two parts and assigning them directly to the member variables - has four. It first clones the parts to temporary variables and then assigns them to the member variables. Why? Without the temporary variables, if the second "new" operation throws an exception (such as bad_alloc), the state of the class would be different and inconsistent from before the call. It would have one original part, and one part from the cloned class.

    There are lots of other simple rules like this that can make code more solid, easier to read, and easier to maintain. If I remember right, the C++ FAQ from the C++ newsgroup contains a lot of them.
  189. I don't know why this dominates the first page... by hummassa · · Score: 4, Insightful
    of the thread... I'm appalled. I'll answer to this, when I would really like to answer to the main post, to maximize chances of you reading me.

    Question 1: what strategies should a developer take to insure that the resulting program is as crash-free as possible?

    Answer:

    a. Use OO techniques and maintain all objects in your system extremely simple; furthermore, maintain all methods in your system extremely short, well-contained, well-defined.

    b. Don't use C++ arrays, ever. Especially not for strings. Use and abuse the STL.
    copy( istream_iterator<int>( cin ), istream_iterator<int>(), back_inserter( v ) );
    is just plain beautiful IMH?O.

    c. Check extensively the behaviour of your constructors and destructors.

    d. Make a object-lifecycle diagram of each class you program. In the diagram, relate it to the neighboring classes (parents, children, siblings, classes involved in design patterns with, classes aggregated, classes value-aggregated, classes where this is aggregated or value-aggregated)

    e. Use, carefully, and always when possible, smart pointers. Remember std::auto_ptr is your best friend -- its limitations are a defining part of its strength. Remember boost::shared_ptr is also a good friend, but its cousin boost::intrusive_ptr is even more friendly -- but use one of those (and their other cousins scoped_{ptr,array}, shared_array, weak_ptr) only in the (rare) cases where auto_ptr does not apply.

    f. As a corollary to (e) above, use boost. This is really an extension of (b), too.

    Question 2: How can I actually implement such a decoupling?

    Answer:

    I would use a simple, socket-base, take-my-data, gimme-my-results scheme. It would be network-distributable, easy to detect if some service is or isn't alive via timeouts... If you want something more sofisticated/RMI-like, SOAP (with binary XML or compressed) may be an option. The simpler the better IMHO.

    Question 3: are there any software _design patterns_ that specifically tackle the stability issue?

    Answer:

    All of them? IMHO, DPs can represent huge tool to increase the stability of a system. Take a look athere [WARNING: PDF] (and in the bibliography) for some ideas.

    I know many of my posts were self-marketing lately, but if you need someone to work with you, I'll be happy to send you my resume... write me at hmassa (at) gmail.
    --
    It's better to be the foot on the boot than the face on the pavement. ~~ tkx Kadin2048
  190. Domain centered/Hexagonal architecture by g_braad · · Score: 1

    I would suggest to create the software using a preferably a stateless domain and connect any relying system using a service/adapter. this way your application would still functoning even when loosing a certain service. You can loosely couple your dependencies... This is often called a Domain centered architecture or as Alistair Cockburn calls it: url:http://alistair.cockburn.us/crystal/articles/h paaa/hexagonalportsandadaptersarchitecture.htm We use it for almost all the software we create, instead of the more traditional tiered architecture.

    --
    F/OSS & IT Consultant
  191. Try a safer and compatible language - FreePascal ! by Ancient_Hacker · · Score: 1
    IMHO you'd be better off writing in a safer, yet still compiled language. A language with fully controllable array-bound checking, data range checking, and overflow checking. A good choice would be Pascal, using "freepascal", which runs on Unix and Windows just fine, and compiles to good code, either 32 or 64 bit.

    And the code is linkable with C code and libraries if you must.

    I've ported several programs from C and C++ to freepascal. In every case the compiler found a handful of previously undetected range and overflow errors.

    Oh, and stay away from the C-like "extensions"!

  192. Monitor thread, signal handling by Kell_pt · · Score: 1

    Hi,

    Maybe you shouldn't aim to have the program crash free. If you assume that crashes will occur, and put in place mechanisms to deal with that, you will have a far more reliable system than if you use a more optimistic approach.

    Smart use of signal handlers and threads should go a long way to ensure the system keeps running. As an example, I'll mention a server I worked on for a couple years, that used the following approach:
    - All subsystems would run inside a try/except block, with exceptions being caught on the upper level
    - A backgroud thread catching signals and ensuring that the subsystems are running

    The server would run the main loop and ensure that the state was recorded at the end of each loop. It could handle even segfaults by resuming operation at the last known state (previous loop). Deterministic errors in an iteration would be dealt with by notifying the admin (only happened in the test versions of course, which had experimental stuff).

    I guess it's more a matter of method than language itself or libraries. :)

    --
    "I don't mind God, it's his fan club I can't stand!" E8
  193. Software Engineering approach. by msid · · Score: 1

    And more specifically testing approaches. Use a standard procedure. Choose the appropriate software engineering model(waterfall,rad, spiral and so on) according to what you have right now and have release cycles along with testing periods. Black and white box testing are the ones I can recall right now. Of course beta testing helps a lot also. This is a crash-safe approach to a crash-free application, in my opinion, although there is no such thing really.

  194. Prove your code has no memory leaks etc by Anonymous Coward · · Score: 0

    You can't use testing to _prove_ the absense of the sort of runtime errors you need to avoid but you can use tools such as PolySpace (www.polyspace.com) to do this. It won't prove that your program does what it is required to but it can /prove/ it to be free of those horrible little bugs that can take days/weeks to find and fix. Alternatively, import the C++ libraries you have to keep into a program written in a language design for producing high integrity systems, e.g. Ada or SML.

  195. Preconditions, postconditions and invariants by igomaniac · · Score: 1

    I assume you _really_ have to make everything in C++, otherwise you should seriously consider developing most of your code in another programming language. The way to make a crash free application is to use formal methods to prove it can't crash. That means specifying preconditions and postconditions for all methods and invariants for classes. There are no facilities in C++ for enforcing this kind of programming, but you can build your own based around the assert.h functionality. The other thing you want to do is to restrict yourself severely as to what parts of C++ you use. Use the STL library for everything, use smart_ptr and auto_ptr in place of raw pointers, use pass by reference as much as possible. Don't do anything fancy like multiple inheritance, operator overloading, advanced template programming or writing your own container classes. These things are better left for library writers. Build some sort of memory tracking facility so you will know about memory leaks (there shouldn't be any if you never use raw pointers, but you never know). Above all, make automated tests for all features you add.

    --

    The interactive way to Go -- http://www.playgo.to/iwtg/en/
  196. Re:Try a safer and compatible language - FreePasca by mkswap-notwar · · Score: 1

    Sadly, the programming language cannot be changed

    Did you not read this part?

    --
    "I reject your reality, and substitute my own!"
  197. Some General Advice by Gorshkov · · Score: 1

    OK .... here goes. I'm an old salt - been a programmer for 25+ years. What I'm going to give you here, now, are my observations and general philosophy ..... your milage may vary. Get the best programmers you can lay your hands on. I don't care what the platform is - bad programmers write bad code. Good programmers write good code. GREAT programmers will make you cream :-) (I know - I have to get out more) Ignore any comments of the type "Use XXX or you're nuts". "XXX is the only way to go, etc." They're trends - I've been seeing comments like that since I started, and code quality is no better now than it was when I was doing hand assembly. Simplify, Simplify, Simplify. The smaller and more discrete your modules are, the less likely you are to have errors. Break the problem down into the simplist, most discrete chunks you can, and do each of them as an individual task. The smaller code will be simpler and easier to test & verify. Use code reviews. Even a guru's eyes will glaze over once he's eyeballed the same source for the nth time .... you need the additional eyeballs. Decouple & seperate. The less each module is dependant on other modules - explicitly OR implicitly - the less likely you are to have unforseen interactions. This also, btw, will help you develop an API that can be made available. Use these approaches throughout your project, and you still wont' have perfect code - but it will stand a much better chance of being correct, and any errors you DO have will be easier to find. This is not an exhuastive list, by any means, but good code is more about approach than specific languages or libraries - it's a state of mind.

    1. Re:Some General Advice by Anonymous Coward · · Score: 0

      And don't forget to code using a decent editor like vi

      DON'T use emacs, it will make your code at least ten times more unreliable!

    2. Re:Some General Advice by Anonymous Coward · · Score: 0

      How true! You should have got a score of 5 for this!

  198. Not crashing is not the same as correct execution by Anonymous Coward · · Score: 0

    If your program is accessing an object that has been replaced or deleted, is it still correct? There is an area of lock-free programming that uses GC but it uses COW (copy on write) to ensure the objects are in a consistent state and the programmers do have to be aware of the slightly altered semantics. For composite data strutures such as collections, you have to be extremely careful that operations linearize correctly (i.e. preserve collection semantics). Naively accessing a data structure without syncronization and assuming that since you didn't crash that your program is working correctly is not very wise. If anything, you should be more afraid of programs managed with GC. Be very afraid.

  199. Re:Try a safer and compatible language - FreePasca by Ancient_Hacker · · Score: 1
    >Sadly, the programming language cannot be changed. Did you not read this part?

    Yeahbut the reasons he gave were not convincing. Freepascal code can be linked with most anything that doesnt have some really bizarre interface. As an example, I've linked it to al lkinds of hellish Windows C DLLs and system APIs. No sweat.

  200. Language is irrelevant by cait56 · · Score: 1

    The key to robust programming occurs long before coding.

    You need a solid design that breaks the system down into objects. Those objects need well defined states, actions and messages. The messages can be implemented as messages or as calls.

    If you have that type of rigorous base the scope of error that you can make in any programming language is very small and very easily diagnosed.

  201. A quick solution to your coding issue by sick_soul · · Score: 1

    > what strategies should a developer take to insure that the resulting program is as
    > crash-free as possible?

    Well, if you ask you're not sure, and if you're not sure, why don't you hire a very
    experienced developer and pay him damn well?

    Let me see, where could you find one? Oh, you're lucky! Here I am :)

    Seriously, an architecture that behaves as you describe is possible. Also, each abstract 'computation unit' should be implemented with easy to read, single purpose functions, whose logic can be formally checked.

  202. Two points by marcosdumay · · Score: 1

    Some things people didn't consider yet:

    First: Your code is as stable as the less stable piece of it. It doesn't matter if you work alone, but if you have a team, make sure that ALL the components of the team are great programmers. Only one bad programmer is enough to destroy all the code.

    Second: Your code can't be more stable than the system it is running on. Some people have pointed things on this direction, but didn't go to the point. You'll need stable (and, probaly redundant) hardware, and a very stable OS (I'd adivise to forget about Windows, Linux-2.6 and weard drivers). All processes running on the machine should also be stable (OS tries to blind you from that, but there is all sort of timing problems that leak), so the less processes the better, and all of them stable. The network should be reliable: no random errors, only packages drop (write another error detection if needed, but you shouldn't need). And, most important, you need a reliable ENERGY SUPPLY. All effort is lost if you suddenly have no energy.

  203. Robustness is in the Process, not the language. by cabazorro · · Score: 1

    It's the process what makes a code rebust and
    manageable, not the language. Here's some tid-bits.

    Design...Code independent. (XML, UML)
    Design...Modular . ( Natural/Logic decomposition of elements)
    Design...By Contract. (Sign the dotted line, read the fine print)

    Code...Follow the semantics design.
    Code on tiers. Upper tier strictly follow design, same
    naming convention same logic..lower tier
    uses generic tools, api's for portability (ADT's, STL, POSIX).

    Test...Traceable...Preconditions..Postcondtions.. al modules are accompanied
    by a test suite and or third party test suite.
    Test...black box, third party. Don't preach to the choir.
    Test...Metrics metrics metrics. Test early, test often, catch the problems
    before the catch you.

    Happy Coding!

    --
    - these are not the droids you are looking for -
  204. MPI & MOSIX by Anonymous Coward · · Score: 0

    if "Basically, it allows users to crunch a god-awful amount of data over several computing nodes" is one of your requirements I would look at http://www.open-mpi.org/ and http://openmosix.sourceforge.net/. These two projects will provide you the library to create multi-node applications( MPI ) and a load balancer for your cluster( MOSIX ).

  205. Some ideas by Chuck+Messenger · · Score: 1

    First, don't listen to the anti-C++ naysayers. C++ can be used to be complex, highly efficient, and bug-free software. It can also be used to make a horrible, inefficient, and bug-ridden mess, if you don't do it right.

    Some basic ideas:

    First: study some of the C++ "best practices" type of books (Exceptional C++, Effective C++, etc). Don't do any production C++ programming until you have mastered these. There are many invaluable tips.

    Second: stay away from fancy object hierarchies. Try to use template mechanisms instead of object mechanisms. Template code is fast, and has superior safety compared to object-style code.

    Third: stay away from explicit allocation. Use STL containers (and other containers from trusted libraries). Going along with this concept: avoid using pointers. I find it is only rarely necessary to use pointers or to allocate things (e.g. Object *x = new Object();). Almost always, I can use a container (e.g. vector x).

    Fourth: If you're doing any multithreaded programming (including across different machines) -- and you are, from the description of your problem -- then you should spend time understanding threading issues. Threads (whether in Java or any other programming environment) carry their own very nasty bug risks. Sure, you can avoid many types of memory allocation problems with a "managed code" environment. But what about deadlock? There's nothing for it but to really understand threading. A book I found to be excellent in this regard was Concurrent Programming in ML. Yes, it uses ML. But it's teaching you about threading issues, not C++ issues. Concurrent ML happens to be a very succinct language for its purpose. There may be excellent C++ books which address threading issues, but I haven't seen any.

    Fifth: a minor-ish tip: when writing multi-threaded C++ code, don't ever use global objects -- only use pointers to global objects. This point may be covered in one of the above C++ books I mentioned, but I don't recall it. The problem is destruction -- when a program ends, you don't know in which order the threads will die, and when the global objects will get destroyed. So, use pointers to global objects, and destroy them explicitly if you need to (I rarely bother).

    Sixth: Look at the Boost libraries (boost.org).

    Well, those are some ideas. I've found that C++ does not suffer from bugginess, despite its reputation. There's a perception that C/C++ code makes it easy to make memory-related bugs (accessing invalid memory, failing to free garbage, etc). While the reputation is well deserved for C, and is doubtless deserved for badly-written C++, it is not deserved for well-written C++. Only rarely do I encounter memory-related bugs (or any serious bugs at all). It's all about coding practices, and using STL-type containers instead of doing memory allocation yourself.

    Hope that helps.

  206. Test first by jodonn · · Score: 1

    Use CPPUnit, and follow test-driven development practices:
    1) Write a test.
    2) Run the test. It should fail.
    3) Write just enough production code to make it pass.
    4) Run the test. It should pass.
    5) Repeat 1-4 until you have a complete system.

    Honestly, this really works, and it'll save you a lot of debugging time in the end. Sure, you can't test every single input to the system, but you can test the corner cases and expected inputs, and that counts for a lot. I'll put my defect counts against any other programmer who thinks that unit tests are for wimps any day.

  207. Correctness by Construction by jeroen94704 · · Score: 1

    If it's really that critical, you might want to take a look at something like Correctness by construction. They actually do not recommend using C++, but with rigorous developer discipline you can achieve similar results to what they describe.

    Also, separating critical and non-critical modules is a good idea. That means you can do the not-so-critical GUI quickly in some convenient environment (Qt, Kylix, whatever) and do the critical stuff the hard way.

    (Apologies for the lame sig below)

    --
    He who laughs last, thinks slowest.
  208. Ultra-stable? by Anonymous Coward · · Score: 1, Funny

    Ultra-stable, crash-free, and runs on Windows.

    Requirements like that make me glad I gave up programming to fish for salmon in Alaska.

  209. Design by drolli · · Score: 1

    The most important thing is: make a model of what you want to do before even thinking which programming language you use. Reduce the semantics needed from external sources to the essential set of features. But do not re-implement semantics w/o need.

    Whereever possible make finite automata models; try to use automated techniques for detecting deadlock in the interplay of these. Wherever possible use known protocols.

    Try to avoid atomic regions in your code for which you have no semantic model (i.e. try to make atomic regions only inside member methods of object specifically designed for "sharing data").

    Avoid unecessary system calls; for the sake of performance and because you never know what will happen.

    If you are sure that you have no circular references, prefer reference counting over garbage collection. (because it is a finite automata!).

    Try to avoid dynamic data allocation - or better: think about the chinks in which memory will be needed.
    Depending on your application write your own memory allocation (Only do this if you know what you are doing), if you have a special idea about the sequence in which memory will be needed (imagine the following memory requests (i write in C, but you should get the point).
    i=0;a=malloc(10000);b[i++]=malloc(10);free(a);a=ma lloc(20000);b[i++]=malloc(10);free(a);
    a=malloc(30000);b[i++]=malloc(10); ......

    In this simple example.

    If finite automata do not suffice at a point use a stack machine.

    *Maybe* use yacc to design your parser;

    Probably necessary to say, but: Run your network of your computing cores should be connected to the GUI only via IPC; Please no shared memory space.

    For the network communication consider existing methods. e.g. Corba - if applicable.

    Ahem; as many things as possible should be as stateless as possible; makes testing easier.

  210. To start with by Anonymous Coward · · Score: 0


    Your software is only going to be as stable as the components that make it up. That means you will have to choose your operating system, APIs and hardware carefully, as well as your choice of programming language. Ensure you have clear requirements from the start (ensure all constraints are defined from the get go). Spend atleast 50% of your time on this pahse. This will lead to a clear design strategy that is half the battle to stable software.

    During implementation you will find that peer review, and static code analysis will help reduce the defect rate (being a good and experienced programmer will also help). Try to use a safe language subset that will reduce program complexity. One idea is to prevent the use of dynamic memory allocation at all (although that will be hard if you have already decided on C++). Use code metric limitations. Peer review all the way long.

    Finally a very thorough full system test (to 100% logical coverage) will help you find the stability you are looking for. Ensure that your test setup provides realistic scenarios and do everything you can to break it, design your software to fail safely. Assume that your software will crash and design is so that if it does crash it recovers in a way so that the crash never mattered in the first place. Use concepts such as hot and cold redundancy to help here. Run your software out of specifications and put it into situations you know it will crash and see how it behaves.

    Proving that any non trivial software will never crash is impossible, you soon start getting into the realms of timing and scheduling analysis at the OS/assembler level and Linux/Windows/C++ are not hard or soft realtime.

  211. Sounds Like Management by Alien54 · · Score: 1
    Sound like the Pointy Haired Boss who knows just enough about programming to be dangerous is making the rules, and this guy is just parroting what he is being told.

    Then, when everyone chops him up, he can point to this discussion as evidence of what experts in the field think of the situation. Which comments are going to be true enough regardless, even if the boss doesn't believe him.

    --
    "It is a greater offense to steal men's labor, than their clothes"
  212. Insightful Article by Blackbird_Highway · · Score: 1

    I've always found this article to most insightful with regard to the sort of effort you are describing: http://www.fastcompany.com/online/06/writestuff.ht ml At the least, it will open you eyes to the amount of effort required, if you really are serious about this. Good luck to you.

    --
    By the perception of illusion, we experience reality
  213. Coincidence from the toilet by defile · · Score: 3, Insightful

    In a desperate rush for some reading material for the toilet, I grabbed what must be a 5 year old C/C++ User's Journal from a storage room. The theme of that month's issue was MULTITHREADING.

    I thumbed through it and came across an interesting article ``ALWAYS HANDLED ERROR CODES''. The idea being that a lot of errors can go undetected because programmers are lazy about checking return values. And why not, who bothers checking printf()'s return value, for instance?

    Simple enough design. The object constructor sets the result, the destructor will abort() the application if the Checked variable is false. The overridden == and != operators evaluate the result, and also set the Checked variable.

    In your functions, instead of return SUCCESS; you write return ErrorCode(SUCCESS);

    Wondering if anybody does this. If I needed something ULTRA STABLE I guess I might...

    1. Re:Coincidence from the toilet by Anonymous Coward · · Score: 0
      Yes, check error codes after EVERYTHING even fclose(). and always pass up erors. Other things are to write cose that "checks itself". For example checksummed data structures. One of the biggest reasons for crashes is a simple bug in the software, one that remains undetected in testing. How to catch and deal with bugs in the code? Check eveything you can think of when ever you can. Is the string passed in have only alpha characters, is the lenght wwithin a reasonable range? the "within a resonable range" test works for floating point numbers too and will catch errors o the type where you are passing in the wrong parameter. Any reasonableness test should pass an "dfail" code back where at csome point things get reset and retried.



      Another thing to do is to REALLY to unit tests. Write a main() for EVERY functions or at least every set of related methods. In you bmakefile have an executable target for each unit test and then automate the unit tests with a "make test" target Verify that the unit tests execuce all codepaths.

    2. Re:Coincidence from the toilet by Anonymous Coward · · Score: 0

      That seems like a strange approach. Why not skip the error codes and just use exceptions to indicate the errors in the first place? Error codes have their place, but I don't think they should apply to everything that can fail. I believe that, where possible, functions should return a value which is meaningful given the function's name.

  214. Crash free and Ultra stable? by TheCount22 · · Score: 1

    Easy, write good code, make sure you write a lot of functions, lots of objects, don't write large chunks of code at once. If there is a library or function already made for something use it, that will avoid bugs and unstability. And test test test test and test again. You could go as far as dividing the program into several smaller application and use IPC(fork + dup2 + pipes) to have them all communicate but I don't think that will help much to be honest. Unless you're using shared memory and message queues, semaphores etc... however keep in mind these things are sometimes very difficult to debug. As far as efficiency just remember one thing the Big O!!!!! for example an algorithm that has a Big O of (1) is better then a Big O of (Log2N) which is better then (N), which is better then (Nlog2N), which is better then (N^2) that will give you the biggest difference in performance, SIMD and -O3 and other optimizations are really just candy and will only give you marginal increase in performance. Spend time learning the debugger, and I've seen a few utilities to find memory leaks, for linux anyway. Oh! and make a memory map sometimes it helps figure out where your leaks are.

  215. Divide and conquer by wowbagger · · Score: 1

    Divide, and conquer - DON'T do the whole app in C++. Split the back-end, the part that does the heavy lifting and uses all the libraries you have in C++. Define (AND DOCUMENT) the interface between the back-end and the front-end GUI - use something like a socket or a pipe or some other form of interprocess communications to tie them together.

    Do the front-end (the GUI) separately. If you want to stay with C++, great, otherwise, use whatever language makes the front-end easier.

    GUIs are hard - they have to be asynchronous, and that makes design and debugging a bitch. From what little you have described, the back-end should be fairly straightforward from a code flow perspective - get data, process data, return results - no event handlers, no callbacks.

    Given the split, you can unit test the back-end a lot more simply, and test for all the corner cases. Unit testing a GUI is hard - again, testing all the async events is a bitch.

    Design the back-end so that if the GUI "goes away", the back-end can continue to operate - preferably allowing the front-end to reconnect to the back-end and pick up where you left off.

    Other than that, here are some general rules I follow in C++:

    Never instantiate a variable until you can initialize it - if that means you define a variable in the middle of a function then do so.

    Use lots of local scopes - you can insert a "{ }" anywhere, and create a scope, with its own variables. This both helps the optimizer know where a variable is used, and it helps the programmer know, too.

    Keep functions as small as possible.

    Treat pointers like guns - keep them pointed in a safe direction (i.e. at an object or at NULL), never make any assumptions about whether they are loaded or not (check for NULL), keep them away from children (junior programmers) by keeping them locked up safely inside objects.

    Where-ever possible, use the "allocation is construction" idiom: If you need to allocate a resource, such as a socket, or mutex, or whatever, create a class object that allocates the resource on construction and releases it on destruction. That way, you can instantiate that object as an auto variable, and when that variable goes out of scope the resource is released, no ifs, ands or buts. It is also released if any exceptions are thrown. One of the reasons I don't like Java is that this idiom won't work due to Java's lazy destructor policy.

    Last but not least - use ASSERT and other logical checks LIBERALLY in the code. If you are making an assumption TEST IT in the code. Track where you are - objects that are passed the __FILE__ and __LINE__ parameters to track who did what where will help you immensely in testing your code.

  216. Ruby and watchdogs by hutchike · · Score: 1
    I suggest you compile your C++ library interfaces as Ruby modules. (You could do the same in Perl but XS is harder). Then you'd get the benefit of your libraries with the resilience and faster development of Ruby. Ruby also has a wide range of test modules to help you with test-first development.

    Since you plan to decouple your various processes, why not use a single "watchdog" process to oversee the others and restart if necessary? This is a commonly used technique in high availability environments. You can guarantee the watchdog is running by putting it in a cron job, whereby it continues running if it can't see itself in the process list.

    Hope this helps!

    --
    Zen tips: Pay attention. Don't take it personally. Believe nothing.
  217. Choose language carefully if lives depend on it by toby · · Score: 1
    Telling him he shouldn't build it in C++ anyway just isn't helpfull.

    If lives are at stake, or this is a seriously mission critical system, language selection must be part of the architecture and design - not an arbitrary choice "because my boss said so".

    C++ is not an inherently fault tolerant language. There are several that are: Erlang for instance.

    --
    you had me at #!
  218. Re:Yeah, c++ hasn't been successfully used before. by Henry+V+.009 · · Score: 1
    I read about a hundred replies to the question, and yours is the first sane one.
    1. There are countless examples of stable, efficiently designed C++ programs. For many developers, it's the language of choice.
    2. Follow best practices. Coding C++ like it was C, for example, is an error. Don't use pointers. Don't use arrays. Use the STL. Use RAII.
    3. Be a C++ expert. No getting around this if you're going to code in C++.
    4. If you are a C++ expert, you will find that C++ offers a lot more than the "easy" languages when it comes to good design.
    5. It easier to hack out a medicore design in Java or C#. And it may even do what you want. But your code will have to be maintained by someone in the future. Good design is worth it, and if you invest the time that you need to in good design, many of the problems of C++ melt away, while other languages begin to a lose a bit of their luster.
  219. Over-engineering does not produce stability by Anonymous Coward · · Score: 0

    It may be that the author simply has not conveyed the scope and rationale for all the elements of the project that he mentions, but this reads like someone intent on developing a lot of trendy, infrastructure that is interesting for the developers to work on, but isn't really necessary for achieving the goals set by the clients.

    Over-engineering results in unnecessary complexity, both in the code and the project organization. And those are among the main causes of instability in software. Further, over-engineering also increases delays and cost, which can lead to a "crashed" project, which is more likely to produce crashing software.

    Ironically, aiming to make a program more "stable" than it needs to be will probably make it less stable, whatever tools are chosen.

  220. Hmm. by Anonymous Coward · · Score: 0

    You forgot to ask for a pony.

  221. The first step. by Xiver · · Score: 1

    If I were you I'd start by purchasing all of Scott Myers books on the STL (Standard Template Library) and read them twice. You'll have a much better idea where to go from there. You even want to hire a C++ guru to help you design the application.

    --
    10: PRINT "Everything old is new again."
    20: GOTO 10
    1. Re:The first step. by Xiver · · Score: 1

      "You even want to hire a C++ guru to help you design the application" should read "You might even want to hire a C++ guru to help you design the application."

      --
      10: PRINT "Everything old is new again."
      20: GOTO 10
  222. A good book you shouldn't miss by GroovBird · · Score: 1

    You should read Effective C++ by Scott Meyers. Twice. And then you should read More Effective C++ by Scott Meyers. And then you should read both of those books again. Every day before breakfast.

  223. No Common GUI by Nicolay77 · · Score: 1

    I can't write multiplatform GUI code with Lisp.

    Not unless I want to have my clients pay a runtime fee for every running copy of the software.

    I have great hopes in the wxCL project.

    --
    We are Turing O-Machines. The Oracle is out there.
    1. Re:No Common GUI by synthespian · · Score: 1

      Not unless I want to have my clients pay a runtime fee for every running copy of the software.

      Apparently, there's this rumour that all commercial lisps charge runtime royalties. This is not true, and such a rumour spreading would be disastrous to lisp vendors.
      Who you're talking about is Franz. Franz wants to be your your business partner, that's what they say on comp.lang.lisp. ;-)
      Other vendors aren't so mean, e.g., LispWorks (the havey Lisp for UNIX, Windows and Mac OS) and don't impose a sick licensing scheme like Franz. The LispWorks LispWorks reads:
      "Q. What's the royalty for delivering my own application?

      A. End-user applications delivered from the Professional and Enterprise Editions are royalty-free, including those using LispWorks ORB, KnowledgeWorks, Common SQL or CLIM 2.0. We believe this is the least restrictive commercial Lisp deployment model available."

      --
      Main difference between the BSD license and the GPL license: one is from California and the other is from Massachusetts
  224. He didn't complain? by Anonymous Coward · · Score: 0

    "Sadly, the programming language cannot be changed..."

    Oh, maybe he did complain. Fuck off.

  225. Separation, transparency, design for evolution by Hier0nymus · · Score: 1

    Physical separation of modules is a very good idea. It helps to contain damage when one part fails, makes the app easier to upgrade piecewise, and forces you to think hard about interfaces. Your first attempts at ultra-reliability will fail. But if you encapsulate well, with clean interfaces, you can make the individual modules ever more reliable over time. Peers of a failing module should detect the failure without collapsing, of course. But consider centralizing the start/stop/restart of all modules in a process manager. Peers detecting a failure report the failure to the PM, but do not take action themselves. I think you have an implicit assumption in "Sadly, the programming language cannot be changed due to reasons of efficiency and availability of core libraries". It's the word "the" - why only one language? Ask yourself if only certain parts of your app are subject to the constraints you cite. Maybe some parts are better suited to a scripting language. I don't mean to preach language, but I like Python so I'll use that as an example: It can interact with C++ by network protocols between separate processes, or within the same process through available APIs; it's good at cross-OS, unless you intentionally use OS-specific libraries; and you could code some parts much faster, leaving you more time to think hard about your interfaces. Use message queues only if you need the asynchronous behavior. If synchronous request/reply in enough, skip the added subsystem. For any inter-process interfaces where efficiency is not a dominant concern, consider text protocols. Your human intelligence is good at detecting errors in text, so this makes the interactions between modules more transparent. It's also handy to test an interface by typing at it. If you go with remote calls between modules, consider whether they need to be object-oriented. Old-fashioned Sun RPCs still work fine, and they're simpler. Object-oriented design is great within a process; but stateless protocols are often best between processes. Treat shooting a module as a primary use case. It's important for isolating failures of course, and also for partial upgrades to a running system. Finally, have a single point of truth for everything the system must know. It's OK to distribute copies of data when you must, but be clear on what module is authoritative for every piece of data.

  226. Experience by JamesTKirk · · Score: 1

    Get a junior-level software development job, and in about 5 years, you'll know the answer.

    Seriously, people post questions like this about once a month, and I can't believe that they actually think they're going to get an answer in a couple of paragraphs to the quesion "how to I write good code?". If it were that easy, someone would write a book, everyone would read it, and there would be no buggy software.

  227. Use STL; avoid pointers; avoid fixed buffers. by Theovon · · Score: 3, Informative

    You can avoid some of the pitfalls of C++'s need for manual memory management and other problems by simply avoiding them. For instance, never do memory management yourself. How? By using STL containers to do it all for you. Next, avoid fixed arrays. Again, let STL do it for you. And, above all else, never do anything where you don't restrict the length. Since you're using STL for arrays, you're good to go there, and you won't end up running off the end of a character array (because you don't use them!). So what you're left with is doing I/O properly. Always limit the the amount of data you read to the buffer size you have allocated.

    I'm sure that there's tons I've left out, but this has worked reasonably well for me. The only problem is that STL can be slow. Sure, map may be O(log(n)), but the constants are huge. Unfortulately, for practical reasons, performance and security are often inversely proportional.

  228. No GUI by Anonymous Coward · · Score: 0

    The buggiest code that you are dependent on is likely to be the GUI libraries from the systems you are targetting. X/Windows and Win32-GDI are full of sh*t code. Historically, these libraries have memory management errors and certainly have leaks.

    1) You need to write a command line version of the code.

    2) You need to employ developers with at least 5 years of professional experience. No noobs allowed.

    3) You need to use as many compilers, native, 3rd party, and GNU with all warnings enabled. Correct all warnings (when possible). This will teach you and your team that not all compilers are created equal. Last time i coded, HP's C++ compiler was too strict when compared to most other compilers.

    4) Follow bullet proof coding standards, hold real reviews and be especially judicious when employing memory management and threads in your code.

    So you know, my background is in Space Shuttle Flight Software development, JSC Mission Control Center software development, and Telecom systems design, development and deployment.

    AND YES, I'm an Anonymous Coward!

  229. It is possible, despite... by pennystinker · · Score: 1

    ... comments and complaints to the contrary.

    Firstly people, please THINK before dropping your favorite high-level language or uber-run-time in as the way to go: perl, python, ruby, java, .NET all started out in, or continue to be, or continue to rely on code written (usually) in C (some in C++). This stuff, in tern, relies on a C runtime library that gives you all malloc, free, sprintf, etc. It may be ugly, but it is there. Then, of course you (probably) are running on some version of Linux, BSD, Mac OS X, Windows, etc. All written in C (and YES the under-lying OSes all have different levels of intrinsic stability, I know, and so do you, please no comments about this they're not productive).

    My point is this: if your favorite high-level language and/or run-time is "ultra stable" then how was this accomplished in poor old C/C++? At the very least C/C++ was involved somewhere in the lifetime of these products.

    I'm now going to regurgitate some already existing comments and ad a few of my own:

    - Yes, as others have said, do consider using a well tested higher-level language/run-time to glue stuff together and optimize where you can. Since you said that you can't do that, I guess C++ it is.
    - Yes, use external components that have a long track record of being "functionally" stable.
    - Testing is great, and using test driven development is a good idea and I certainly would make this this the central "arch" of your development efforts.
    - FORMAL development has been demonstrated to give the most consistently good results in terms of "quality" of produced code. What I mean by this is to the extent possible: PROVE the correctness of your code, formally. There are plenty of books to help you get started. A place to start would be David Gries' book "The Science of Programming", and excellent text that will make you a better programmer no matter what.
    - Since you like I are human an imperfect it is in your best interest to assume that failures will happen. Then I would suggest KISS (keep it simple stupid). Build individual parts that are VERY simple, easy to understand, and highly unlikely to fail individually and assemble them into more complicated systems. Again, the idea is that along with each assembly step keep the individual assembly steps as simple as possible.
    - Code defensively in two domains: Exceptions/failures - to the extent possible write your code to be able to identify and recover when failure has occurred. ALSO, and this is as equally important: Sanity checks - wherever possible DON'T trust the results from each of your components. Wherever you can implement sanity checks on incoming values from each one of your modules. This will go a long way to helping identifying where a 36 hour computation went wrong.
    - Log, log, log. You won't get it right the first time but the more information you have to fix your mistakes the better.

    In order to help you assemble a lot of simple parts you may want to consider Linda (C-Linda and C++-Linda also exist). It might make building your system easier.

    Hope this helps

  230. misc. advice and a small rant? by EsbenMoseHansen · · Score: 2, Interesting
    C++ takes a lot of platform-specific work to become portable,

    Where do people get this idea? I have ported quite a few applications, and usually the porting done by locating the libraries you need on the new platform, and fix a few oddities in the current platform (like closing sockets in z/OS or switching to unsafe multitasking (p-threads) on windows. Porting to linux is so trivial that I often do it just to get access to the superior tools available there, especially valgrind. GUI is the exception, of course, unless you use a x-platform kit from the beginning.

    Which leads me to my recommendations, in no particular order

    • Use Valgrind. A lot
    • Use a good toolkit. If GPL is acceptable, consider QT.
    • Consider a "packet" or a "transaction" based approach, that is design every application to take in a package, process it and return/store the result. This sort of applications are easier to automatical test
    • Avoid huge application anywhere... no more than 100 classes per application, no more than 1000 lines per class
    • Use automatic, integrated unittest
    • Use automatic, daily run integration/function tests
    • Do not accept complication designs
    • Avoid close sourced libraries. Be aware and fix library issues.
    • Avoid incompetent developers on critical components. Let them make the GUI/statistic/other fringe components.

    The above approach works for me. You mileage may vary.

    --
    Religion is regarded by the common people as true, by the wise as false, and by rulers as useful.
    1. Re:misc. advice and a small rant? by after+fallout · · Score: 1

      A couple more things:

      • Use subversion (correctly, maybe after reading the book: http://svnbook.red-bean.com/)
      • Use Bugzilla (or Trac, but that isn't quite as good yet, OTOH it integrates with subversion; or use sugarcrm's bug tracking software, but again that isn't quite as polished)
      • Make every new feature go through bugzilla as an enhancement.
      • Never do more than one thing in a function (if your function requires more sentence structure than that of a 6 year old to describe what is happenning: you are doing too much)
      • Head every function set with the following comments (consider using xml based versions of this that can be exported to an html page by using a generator):
      //Summary:
      // the 6 year old's description here
      //Requires:
      // name of each function and data type used here along whith the file they are located in
      //Preconditions:
      // the state expected for each variable that your function uses before the function begins
      //Postconditions:
      // the state of variables and the return value as the function completes
      //Throws:
      // possible exceptions thrown by the function
    2. Re:misc. advice and a small rant? by Jerry · · Score: 1
      "# Use a good toolkit. If GPL is acceptable, consider QT."


      QT is an excellent toolkit, and EVEN IF GPL is NOT acceptable Trolltech offers a QT commercial license.
      As far as portability goes I find it easy to use compiler defines automatically select code segments which would be platform specific. For example, Oracle doesn't require intermediate selects in an aggregate sum to have a name but PostgreSQL does. Appending a select name to a sql statement is a mere "if" test. With the right choice of fonts the GUI front ends are also transparent across Windows and Linux desktops.

      --

      Running with Linux for over 20 years!

    3. Re:misc. advice and a small rant? by oever · · Score: 1
      Use a good toolkit. If GPL is acceptable, consider QT.


      If GPL is not acceptable, buy Qt.

      --
      DNA is the ultimate spaghetti code.
  231. Build it around a stable database by Mutatis+Mutandis · · Score: 2, Informative

    I am by no means a specialist in this field and of course I do not know whether your project actually allows this approach.

    But if I were asked to do this, I would take a database (a stable release of MySql is what I would choose) and use it both as the persistent object storage and communication module. The GUI and the number-crunching module(s) would be set up to primarily communicate through the database, rather than directly with each other. A task state/queue table in the database would inform the modules what tasks have not been assigned yet, are running, are complete, have not returned in the expected time, or have failed. This would make it asynchronous and highly traceable; databases are (supposed to be) good at managing the interactions between multiple user processes and still maintaining data integrity. Admittedly this is not the best approach if you want your results real-time.

    The central managament of the processes could be kept minimalistic and simple, and "therefore" robust: Some very simple communication with number-crushing processes to test whether they are alive (a TCP/IP socket read-write might do), re-opening a task that has not returned in an expected time period (if its process still returns later, the newly started process will have to detect that its work was already done, and discard its results instead of writing them back), and perhaps signalling critical task completion to users (by GUI message, e-mail, text message, ...). The central management would not have the startup responsibility for distributed number-crunching modules, that would remain with the local servers they are running on. Such a process can then "knock on the door" of the database, register its presence, and take the next available task, or wait until one is available.

    The persistent form of the core data structures would be in database tables, but the modules would of course have their share of the data in memory as class representations of the data structures, defined to be initialized from the database tables and written back to them. These class representations of the data structures then could be in a common library shared by the different modules, but alternatively you might opt for different class representations for e.g. the GUI and the number-crunching modules if that is more efficient (it often is) and even write them in different languages if that is more convenient. I admit that that adds to the amount of code and therefore to the amount of bugs. On the other hand, you could write two "completely" independent implementations of the same task.

    If your number-crunching is complex and long, then evaluate whether you can write back intermediate states to the database as a recovery point, or even split the calculations in completely independent modules, each one starting and ending with a given database state. The desirability of this depends, of course, on the balance between I/O and processing costs. If you have modules that are relatively simple and safe but need to work quickly through a large amount of data, you could consider database stored methods for these; not very distributed but it reduces the amount of I/O and they can easily be called by client processes.

    The database does not care in what language the different modules are written, so you can then write every one in the language that is most appropriate. For example, there may be no reason at all to write (parts of) the GUI in C++ -- and that is something I would try to avoid. If performance allows it, I would use Java for the GUI, both for portability and simply to avoid the mess of writing user interfaces in C++; in my experience that does not tend to be the most stable solution.

    For the C++ part I would start by structuring pretty strongly; write a large number of simple classes instead of a smaller number of complex ones, and test every class before you move on to the next level. The "salami approach" works well if you plan it well. It is perfectly possible to write very ro

  232. ultra-stability in c++?? by mobileink · · Score: 1
    "I need to create an ultra-stable, crash-free application in C++. Sadly, the programming language cannot be changed due to reasons of efficiency and availability of core libraries." Those are bogus reasons. Presumably the system has certain performance and stability requirements that must be met. Implementation language is not relevant, so long as those requirements are met. There are many ways to meet such requirements regardless of language.

    If you want "ultra-stability", then choose a language designed for that purpose. Standard ML is the obvious choice - why waste time testing when you can prove the correctness of the program from the get-go?

    "Availability of core libraries" - what relevance does this have? It's pretty standard practice these days for languages to provide access to external libraries, regardless of implementation language.

    Once you have a provably correct and therefore "ultra-stable" implementation, attack the performance issues. Profile to find the bottlenecks. Use better algorithms. Recode performance hogging functions in assembly. Most obviously, upgrade the hardware. It's much cheaper and practically risk-free.

  233. Bullshit by everphilski · · Score: 1

    C++ takes a lot of platform-specific work to become portable

    Bullshit. C++ written well is portable by default (between windows and linux). There are a few minor issues between linux and sgi.

    1. Re:Bullshit by TheNetAvenger · · Score: 2, Interesting

      Bullshit. C++ written well is portable by default (between windows and linux). There are a few minor issues between linux and sgi.

      I agree.

      This is by nature one of the biggest strengths of C and C++, how someone could conclude that by using C++ adds some sort of complexity in cross platform development actually amazes me.

      If it adds complexity, in comparison to what? I would like to see the poster above you explain what is actually easier to use for diverse application development that is actually better at cross platform.

      And if they start with Java, la la, then they need to get a life and see what JAVA is built upon itself.

      C and C++ is a great solution for cross plaform development, look at the nature of Linux, BSD, and even NT and then ask why they are as portable as they are. Do people think these OSes would be more portable in another language?

      Take Care.

    2. Re:Bullshit by gangien · · Score: 1

      C++ is at it's heart, quite portable.. until you get outside of doing simple I/O/data structure types of things.

      want an example?
      Sleep/sleep in windows it's Sleep, in *nix it's sleep

      of course one line to get rid of that aggreivation.. but that's just a simple example.. try doing something like a hash table.. one of the products i'm working on compiles in visual studio 6, and gcc on other *nix (linux, solaris, hpux, aix). that code is completely hacked.. why becuase of sleep/Sleep, because of all the little OS specific changes or the big ones like having to import STLport vs the gnu implementation. Or some class not overriding operator like they do on the other platform.. yadda yadda yadda, there's a bazillion of these, and they're not hard to uncover.

      Or even better, want to statically link an app? that's most definiatly NOT a portable thing.. and not as simple as it should be on any platform.

      These things don't exist in the java world..

      yes java is built on C++, so they in effect, do the dirty work, so we can take it for granted. Or are you going to be doing asm programming, because C++ is based on that? No, you would use a higher level language so you don't have to worry about registers and crap

      But java runs into platform specific problems as well.. lack of proper file buffering on windows was a big performance hit on our code somewhat recently. Also EBCDIC vs ASCII for character encoding.. but all the java issues are issues in C/C++ as well. So basically the problems of C++ are a superset of the java ones.

      Not to mention that C++ requires build machines for each type of os/arch you want to build on. which requires setting up build enviroments and lots of other hidden fun.

      Does this mean never use C++? absolutly not. in some cases it's far easier, or nessecary to use C/C++. (kernel API calls, or building a kernel itself... though this mgiht change soon..) or efficiency, unfortunatly java isn't fast enough to be a 3D game platform yet. or legacy apps. but for most apps, it's by far a better choice than C++. What are the points for c++ over java? speed (which is usually far overrated) and system level stuff, so you have 1.5 reasons to use C++ over java, and a bazillion more reasons to use java over C++

      Really though, java isn't "the choice" either. It's to bad people aren't more accepting of other languages.. we might be well over the hurdles that java/c# and their reliance upon VM's present. Which would lead to even more stable code being written. One thing i love about .NET (supposidly, i've never actually tried it yet :( ) is that you can combine languages.. imagine the power of that.. some things are better off done in a functional language, some c++ would be better or prolog or whatever.

    3. Re:Bullshit by EsbenMoseHansen · · Score: 1
      want an example?

      Sleep/sleep in windows it's Sleep, in *nix it's sleep

      I use sleep either place, but then I do use the mingw toolkit. So perhaps you just need to use a better toolkit? The remaining problems you have all seem to stem from your toolkit. I have never used visual c++, but as I understand, it is a really substandard toolkit, not really ready for production use. Use gcc :)

      As an aside I lie. I use nanosleep(), which is preferable in any case.

      As for Java, java is a modern Fortran. If you need a modern Fortran, by all means, use Java. Java has a host of problems and gotcha's (from the top of my head: unsafe multiprocessing, no RAII, no metaprogramming, no multiple inheritance, surprising handling of method calls from constructors). I would only choose Java for external reasons, e.g. Mandatory language, limited skill people that already know Java. Otherwise, I would use either C++ or python/Haskell/Ruby depending on the circumstances.

      --
      Religion is regarded by the common people as true, by the wise as false, and by rulers as useful.
    4. Re:Bullshit by TheNetAvenger · · Score: 1

      You have valid arguments; however, my reference to using C++ or C for cross platform development was directed a bit more at a lower level.

      There is a big difference between writing for an architecture, specifically hardware and writing for an OS API and OS Libraries.

      Porting applications from OS to OS is not easy at all. But porting the Linux Kernel or the NT Kernel from x86 to PowerPC to you name is easy in comparison to other solutions.

      In fact C++ and C tends to be the backbone of the cross platform availability of different OSes on different hardware architectures.

      If you are writing an application to run seamlessly on Linux, Windows, OSX, etc... There are not even any GOOD solutions, and this is more from the inherent differences in the OSes and the User models, as well as the API and library differences.

      Take for example some good open source projects that run on many OSes, they tend to sacrifice the OSes strengths in place of keeping the code as simplistic and portable as possible. They tend to implement their own controls, etc instead of using the inherent OS featurea available, making the application clumsy for novice users.

      This is an area where open source needs a shot in the arm, as a Mac user on average looking at a psuedo message or dialog box is not what they know and it will confuse them quickly. (Using Mac as an example only, it applies to all OSes with novice users.)

      However, this does not mean it cannot be done and done well. For example (hate to use this example) - Microsoft Office uses a lot of common code between the OSX version and the Windows Version.

      However, the Microsoft Mac team, are real Mac users, and Microsoft Office for OSX looks and works like an OSX application, to the point that Windows users were jealous at one point of some of the interface designs that were common on OSX being used in Microsoft Office. However, this isn't an exact shared code based, but for that loss of development time, Office for OSX is a true to OSX, as much as Office for Windows is true to the Windows UI.

      I wish there were some good solutions that not only offered a better level of cross OS development, but JAVA isn't one of them. It is clumsy, goes out of its way to NOT behave like native applications on the OS it is running on, etc.

      You can develop an applicaiton like that and expect it to be successful, people use OSX and Windows because of the consitency of the applicaitons, Java breaks that for the average user.

      We are at a time where we need to NOT AGREE on common UI models, as each OS has strenghts and reasons people use them, but instead focus on creating solutions that assist in not only porting code from one OS to the other, but also helping the developer mold each OS specific version to take advantage of the OSes and their strenghts.

      This is not only things like using the common dialogs, controls, etc, but also realizing how people use OSes differently.

      OSX users tend to use their computers vastly different than Windows Users, just like *nix users use their OSes totally different, and then add in the GNOME, KDE, etc model differences.

      We truly have the brain power and technology to create tools to do this. Tools that help a developer by even suggesting to a developer that this is for OSX, you should be aware of A, B, C and consider implementing your applicaiton to fit what OSX users expect.

      How annoying is it to be on a Windows machine and run a great cross platform open source applicaiton and have it fail to support simple things like drag and drop from files, drag and drop of text between the application and the OS or other applications on the OS, etc.

      Insert OSX and *nux examples as well.

      Didn't mean to extend this conversation down a different road too much, but I feel some people need to think of these things further.

      I also wanted to make it clear that cross architecture is a stronger case than cross OS development for C++, although it does quite well even for OS cross platform development, and you aren't dependant on anyone. Java for example, you are dependant on Sun and if they break something in the next release, etc. With C++ for the most part you are depending on yourself.

  234. I think there's a book on that very subject! by iBod · · Score: 1

    "Ultra-Stable Software Design in C++"

    - Malmesbury & Duke, 'Tech Stuff for Morons' series, 1998

    Other titles in the renowned M&D catalogue include: -

    - "Make Your Own Canoe from Chicken Wire", 1982
    - "The Importance of Pig Iron in Modern Aviation design", 1990
    - "1001 Cajun dishes featuring raw sewage", 2005

    A great series. I have a bookcase full of 'em.

  235. Please Explain... by Svartalf · · Score: 1

    What you just posted did NOT make any sense. One Cycle? Of What? Please clarify what you just said.

    --
    I am not merely a "consumer" or a "taxpayer". I am a Citizen of the State of Texas
    1. Re:Please Explain... by tgv · · Score: 1

      A cycle is a chain of connections that connects to its own starting point. Something like A -> B -> C -> A. If you unlink A, it won't be deleted, since there is still a reference to it (namely C). Consequently, the whole chain will stay in memory. If your app produces such circular data structures regularly, memory will slowly fill up.

  236. Have you have flown on a commercial airline? by EMB+Numbers · · Score: 4, Informative

    Have you have flown on a commercial airline in thelast 30 years? If so, you trusted your life to software.
    Thare is a standard called DO-178B Level A that applies to aircraft software upon which lives depend. There is a saying in the commercial avionics business: "Nobody has ever died from software failure on an airplane, yet." There have been some accidents where software played a role, but I won't quibble with that now.

    The point is that safety critical software is developed routinely. It has been developed in asembly language. It has certainly been developed in Ada, C, and sub-sets of C++. It is expensive. Validation of avionics software and certification in an aircraft can easilly cost an order of magnitude more that just writing the software, and writing the software using required processes and producing required artifacts is not cheap either.

    1. Re:Have you have flown on a commercial airline? by Anonymous Coward · · Score: 0

      If I`m not mistaken, it sometimes takes three different computers with differently designed pieces of software and the system makes a vote: the majority decision is taken.

  237. Re:I don't know why this dominates the first page. by Anonymous Coward · · Score: 0

    You say "IMHO" too often.

  238. Nonstop Kernel: VMS??? OSF/1-Tru64??? HPUX??? by mosel-saar-ruwer · · Score: 1

    I googled a little, and came to this page:
    http://h20223.www2.hp.com/NonStopComputing/cache/7 6715-0-0-0-121.html
    which in turn led me to this old PDF DOCUMENT from 2002:
    http://h20223.www2.hp.com/NonStopComputing/downloa ds/KernelOpSystem_datasheet.pdf
    But I can't for the life of me tell what this operating system is supposed to be.

    Is it Digital VMS? Is it Digital OSF/1-Tru64? [OSF/1 is mentioned on page 9 of the PDF document.] Is it some flavor of HPUX?

    Or is it something else entirely?

    And, parenthetically, I'd ask: Why do the droids in Sales-N-Marketing insist on publishing this crap that doesn't even begin to answer the most fundamental questions their customers might have?

  239. Really, what's wrong with C++? by JourneyExpertApe · · Score: 1

    After reading some of the replies, most people seem to take it for granted that C++ is inherently unstable. The main reason cited is memory leaks. Well, guess what, C++, if written properly, can have garbage collection. The answer is smart pointers. Specifically, check out the boost smart_ptr module. I find that if I wrap all calls to new in a shared_ptr or shared_array, my memory leaks go away. If I need bounds checking on an array, I'll use a std::vector class. And whenever type casting a class, I'll use a dynamic_cast, followed by an assert() of the result. Of course, there's always the possibility of introducing a memory leak when sharing pointers with another library, but at some point, you have to trust some code to be crash proof (like the .NET runtime or the JVM). In short, the key to safe C++ is smart programming techniques.

    Also, this is intended to be run primarily under Linux, with the possibility of a Windows port later. Can anyone tell me how good the Mono class libraries are? I would think that, like GCJ, Mono is somewhat incomplete and/or buggy.

    --
    If you can read this sig, you're too close.
    1. Re:Really, what's wrong with C++? by Anonymous Coward · · Score: 0

      No sorry - there's just so much more unsafe with C++ (and C for that matter) than memory leakage! Array overruns, implicit casting, dereferencing null pointers, etc. The other problem with C++ is that it has been, in my experience, terribly UNportable - between compilers and/or platforms. And, to my knowledge, there is _still_ only 1 C++ compiler that is 100% standard compliant. :-(

  240. How is this a troll? by shm · · Score: 0

    The parent refers to Erlang, and is modded "Troll."

    1. Re:How is this a troll? by root-a-begger · · Score: 1

      Precisely how is this a troll? The vast majority of resposes strongly state that C++ is not the best choice for the entire app. I also state that the existnig C++ libraries should be used but with a more appropriate language to control the entire system. Using erlang in this respect is no different from the first post that suggests using managed code.
      I suggested erlang because I am a recent convert and am realizing extreemly high productivity and can sleep better at night knowing that my system architecture is rock solid.
      My post was hardly a troll. It is honest advice about a choice of language that is fully interoperable with C++.
      Please save your mod points for vi vs. emacs posts.

  241. Wait, why isn't this moderated Funny? by cocoa+moe · · Score: 1
    b. Don't use C++ arrays, ever. Especially not for strings. Use and abuse the STL.

    copy( istream_iterator( cin ), istream_iterator(), back_inserter( v ) );

    is just plain beautiful IMH?O.

    Well if this is beautiful, then why is it that I have no idea what it is doing? Beautiful code is unreadable? Congrats! You are a genious.

    How about Syntax like:

    a[3;12]=b[11;2];

    That would be beautiful. Iterators are a misunderstood concept.

    1. Re:Wait, why isn't this moderated Funny? by Wolfier · · Score: 1

      RTFP.  It's obvious the parent is restricting the context in C++.

      YOU have no idea what it is doing.  You know what?  *I* think that line looks trivial.
      Since neither you or I can represent the general developer population, whether YOU can understand or I can understand the line has absolutely nothing to do with beauty.  If beautiful code is unreadable by YOU, perhaps you should study the language more.

      Of course if I can choose a language I'd greatly prefer Ocaml, Lua, or Ruby than anything else.  But in the context of **C++**, your a[3;12]=b[11;2] is utterly pointless.

      Of course, since C++ is a multiparadigm language you can still use write functors and use a(3,12)=b(11,2) to accomplish the syntatic sugar you want.

    2. Re:Wait, why isn't this moderated Funny? by Anonymous Coward · · Score: 0

      Well if this is beautiful, then why is it that I have no idea what it is doing?

      Maybe because you haven't read a single book about C++ that was written after the stone age, that is, about 1996.

      This line is more verbose than strictly necessary, but for the C++ context, it is beautiful . If you don't like it, go on programming in a 1960s style with explicit loops and indexing, but try not to drag your coworkers down to your level of expertise.

  242. There's no substitute for maturity by Anonymous Coward · · Score: 0

    Your post convinces me even more that there is no substitute for maturity in writing bullet proof code. It isn't the language - C and C++ are fine, mature languages for mature programmers. This has nothing to due with age.

    If even a single bug is allowed into a daily build, then you will not have a bullet-proof program. Most commercial teams cannot take that high standard due to costs and schedule pressures.

  243. A real answer by bokmann · · Score: 1

    Here is a real answer, unlike the dozen or so I just saw perusing existing posts.

    The goal of 'crash free' is going to be impossible... Even if you could write perfect code, you already stated you need to rely on third party libraries. You can only be as stable as they are. You want to change this goal to be 'high availability', which is a system architecture term that you can now google on and find some design principles, including redundancy. You want to be 'resiliant to crashes'. Keep in mind that this will affect everything down to the design of the computer it will run on (do you need 2 hot-swappable power supplies so that one can fail without the app going down?)

    While this term is so overused as to almost be meaningless, you will want to keep in mind a 'service-oriented architecture'. What I mean is that you will want to build the modules you discuss in your post as 'services' that other components will rely on. The components that rely on the services need to be resiliant to failure, with strategies such as queueing a request that isn't fulfilled (due to a crashed service), redirecting the request to another available service, etc. You want to be able to decompose your problems into 'problem chunks', and think of your various modulces as 'producers' and 'consumers' of these chunks. the producers and consumers shouldn't talk to each other directly; there should be a blocking queue between each so that producers and consumers can be decoupled - the producer can keep producing while consumers can come and go, and consumers can have work to do if a producer crashes and has to restart.

    That should give you a good start for googling on some architecture.

    Lastly, if you really want your code to have any hope of being nearly bulletproof, you have to have some discipline, in the following forms:

    1) Use Coding conventions, and stick to them. Automate the ability to check compliance. With coding conventions, maintenance becomes easier, defects stand out, etc.

    2) Write unit tests, and have good code coverage. In C++, you are going to have to worry about bounds checking, etc. Unit tests are the best way to prove your code works.

    3) Document things well. Don't document what the code does, document WHY it does it.

    4) Use some Version Control/CM processes and tools, like CVS or Subversion. You ALWAYS want to be able to recreate a particular state, for instance, if you do have a defect and need to be able to recreate it in a predictable environment. Besides this, CM gives you a project-lifetime 'undo' capability.

    5) Use static source code analysers like lint. (There are dozens of these in Java, like PMD and FindBugs). Even if these tools cannot find the really hairy problems for you, they do find defects and do so cheaply and easily, compared to finding the same defect yourself, or worse, after your software is in production.

    Hope this helps.

  244. Consider isolating C++ by Julian+Morrison · · Score: 1

    It may be necessary to use C++ for parts of the system, but can they be isolated as a seperate adjunct process? That way, your damage is limited and your main, secure process can keep a watchful eye on the C++ process.

    Design the C++ side to be stateless, so a halt-and-restart can occur losslessly between RPC transactions.

  245. Ahh... by Anonymous Coward · · Score: 0

    I see the .NET astroturfing has begun.
    How much does each score 5 post pay?

  246. One more point. by Wolfier · · Score: 1

    Use Electric Fence, Valgrind or Purify and automatic test your program to death using deterministic and then randomized (in key dimensions) inputs - let the test run itself for days. This technique can uncover a lot of stability defects.

  247. Only the Paranoid Create Stable Code by rocker_wannabe · · Score: 1

    Only the paranoid, diligent programmer stands a chance of writing "crash proof" code. The reason code crashes is because some error checking is missing. If the "worst case" scenario is always handled then the program my quit functioning as expected but it won't crash.

    The other major reason programs quit working, and possibly cause a crash if there isn't sufficient error checking, is because of memory leaks, which are due to poor architecture. There is no substitute for using a "formal" architecture, like state machines, to avoid unexpected code paths to be executed. The formal architecture will help a programmer determine to best point to allocate and free up memory that will avoid memory leaks. Garbage collection is a great idea to help harried programmers get something out the door but it can't take the place of good architecture.

    My two cents worth.
    --
    "Meaningless!, Meaningless!" says the Teacher. "Utterly meaningless!"
    1. Re:Only the Paranoid Create Stable Code by Anonymous Coward · · Score: 0

      ... like state machines ...

      It amazes me how many engineers don't get that. I've created some (admitedly nasty) state machines and I've almost always had a colleage complain that they can't deal with them. They almost always shut up when I ask them, "then, give me a better solution". I've had one guy try and fail and another come up with what was basically the same state machine with a different veneer, and no complexity reduction whatsoever.

      Dealing with complex problems unavoidably means a complex solution. i.e. there is a minimum level of complexity required to solve any given problem, no matter how you do it.

  248. TSP is the answer. All Hail TSP. by diverscuba023 · · Score: 2, Funny

    Ah, but test driven development flies in the face of the new government backed, SEI approved software development silver bullet called TSP (Team Software Process). And by following TSP you too can consider just how much better it is than test driven development while waiting for your co-workers to inspect your code for a few months.

    1. Re:TSP is the answer. All Hail TSP. by ecloud · · Score: 1

      Ah, I thought you were referring to Tri-Sodium Phosphate...

  249. The whole charade by Gotebe · · Score: 1

    All of the above +... Use C xor C++. When must mix (OS or external library calls), wrap. C++, if not used with STL, boost, exceptions, SafeGuard, RAII, the whole sharade, sucks beyond repair. P.S. If you use STL and have exceptions disabled, leave the project right now or I'll shoot :-)).

  250. Learn to use STL and don't *ever* type "new[]" by Joce640k · · Score: 3, Informative

    1) Learn to use STL.

    Do *all* memory management via STL vector/string.

    2) Don't ever type "new[]/delete[]".

    Just don't do it. Not. Ever. Use std::vector instead.

    "Arrays are evil" - the C++ FAQ.

    PS: You can still use malloc()/free() but only as a last resort in low-level classes which are designed for data storage.

    3) Get a reference-counted pointer and use it.

    Automatic memory management...'nuff said.

    4) Attach an alarm bell to your "~" key.

    If you're writing destructors for classes which don't control system resources (eg. files) then you're probably doing something wrong - see notes 1, 2 and 3.

    --
    No sig today...
    1. Re:Learn to use STL and don't *ever* type "new[]" by Retric · · Score: 2

      IMO: Use Java(ick)/Pascal/(stable high level lanuage) and link to your own custom C++/ASM lib for the stuff that needs to be *fast*.

      By spliting the app into more than one language you end up with a clean code seperation between the *fast* code and the *stable* core. Chances are you don't realy need to work out complex thread communication all that often, but if people think the App needs to be fast then they will start optimising stuff that they have no reason to thouch. If this is not fast enough profile the code and see what you need to work on. Chances are your app is going to spend over 90% of it's time on less than 10% of it's code so you are free to keep everything else clean and only make a mess of that fraction.

  251. Read some standards by Anonymous Coward · · Score: 0

    I'd suggest reading Software Safety by the Numbers at http://www.embedded.com/showArticle.jhtml?articleI D=19201765 on IEC 61508 for safety critical industrial software or getting a copy of RTCA DO-178B from http://www.rtca.org/ for avionics.

  252. Automated Testing and Code Reviews by PaulMichaelReilly · · Score: 1

    Whatever else you take from the multitude of responses, your system will be better off for having formal design and code reviews among small subsets of your team. And collect all test cases into a framework such that any potential release will have to pass ALL previous tests. These two steps alone will go a long way to making your application stable and correct.

  253. No Simple Answer. by SWestrup · · Score: 1

    Efficient, bug free code is the Holy Grail of software, and no one has achieved it yet. All I can do is give the standard answers:

    1) Nail down the specifications and don't let them change. Once you have a design worked out, any changes to the goal can cause unforseen complications and bugs.

    2) Have the system designed by someone with a lot of experience in system design and a proven track record of low-defect designs. Bugs caught and prevented in the design stage are always the cheapest to cure.

    3) Take the estimated time for testing and debugging and double or triple it. Cutting time corners is one of the main ways bugs get added or lost. Remember that the really low defect software houses document and justify EVER SINGLE CHANGE TO EVERY LINE OF CODE. This may be overkill for you if you aren't remotely programming a $10 million satellite or writing life-critical code but its how you make sure your defect level is as low as possible.

    4) Hire veteran programmers. Its no guarantee of bug-free code, but among better programmers, the longer they've been programming, the cleaner their code is. Besides, they'll know all of these points already. The obvious corollory is not to hire bad programmers, no matter how much experience they have.

    5) Turn on all warnings and errors, and use an additional external verifier. I prefer Gimpel Lint, but there are other lints out there as well that can help you. Generally, any tool that can help in the verification process should be used.

    6) Code verification walkthroughs. Its amazing how much cleaner folks write code when they know that they will have to show and explain it to a random co-worker.

    7) Have unit tests of each module and/or code section as its written. Keep the tests and use them for regression later. Have someone OTHER than the writer of the code test it.

    8) Pray to the Deity of your choice that the inevitable bugs won't be serious.

  254. Boost. by imbaczek · · Score: 0

    especially Boost::Python.

  255. Try/Catch? Timers? by henrybg · · Score: 1

    Ok, my ideas may be a little juvinile, but specific programming instructions that will work in the testing phase:

    1. Find the error message possiblities with every function you call and handle them with try/catch.
    2. Implement a timer that will send a message every x seconds after you start it. Start it before every loop, and stop it after the loop completes. If the loop turns into an infinite loop, your timer will throw an error message (with should be handled) in the function body of that loop.
    3. To keep all of your modules seperate, either use managed code, or just write an if statement checking for its existance. If it's not there, let the user know so they can fix the issue.

    If you can program in these three things, it will be up to the user to respond to problems, rather than the programmer. Once you've tested this application, you'll probably have a good understanding of what responses the user still has to make on a regular basis, and program those in as well.

    It's all about making sure you know all of your specifications, making designs that will work within the design, as well as work without. If you can test all design modules to a point where the programmer and user will agree on its functionality, you should be in a good place to sandwich test with another couple modules.

    Checkout IEEE software engineering docuements for help with design and testing ideas.

  256. Virtual machines by billcopc · · Score: 1

    Easy answer: just learn to code, dammit! :P

    No, seriously something like a virtual machine might be the way to go. Yes it's horribly contorted, but see each indirection as a choke-point for leaks and glitches. Build in as many idiot-proof checks as you can, and do extensive bounds checking and whatnot. If you can make the outer layer of your app crash-proof, it will form a sort of "condom" for the innards.

    --
    -Billco, Fnarg.com
  257. Code Complete by Rick+Genter · · Score: 1

    Frankly, if you just follow the guidelines established in Stephen McConnell's Code Complete, most if not all of your concerns will be addressed. The guidelines pretty much apply independent of language, operating system, etc.

    --
    Don't underestimate the power of The Source
  258. Re:I don't know why this dominates the first page. by Chemisor · · Score: 3, Insightful
    > copy (istream_iterator(cin), istream_iterator(), back_inserter(v));
    >
    > is just plain beautiful IMH?O.

    I'm sorry, but I just can't agree. It might appeal to a mathematician who wants to see everything use functional notation and hates every language except lisp, but to a non-abstract-elite-ivory-tower-mathematician this is absurd. cin is not an array of integers and the use of the adapter obfuscates the fact that you are using a conversion from a char array to an int. The back_inserter also makes it harder to see where the data is going by losing "v" in it. Many would also frown at it for taking a non-const reference, although since it is a standard adaptor it is probably ok.

    C++ programmers are often unnaturally attached to efficiency and have to be watchful for template bloat. Your copy generates 88 instructions, whereas an equivalent iterative solution is only 33 instructions long, most of them belonging to the inlined push_back. Not only is the generated machine code smaller, but the source code is smaller as well, and is far more readable, making the algorithm obvious at a glance to any procedural programmer, who make up the majority outside the hopelessly out-of-touch with reality academia.

    int n;
    while (cin >> n)
    v.push_back (n);

    Academics love integer and float arrays because that's what they usually work with. Scientific simulations produce data in that form and require processing programs that take something from a data file, crunch some numbers, and output something to cout. In the real world people work on user interfaces, databases, and other complicated things, where one normally works with arrays of objects rather than numbers. If you ever tried to apply a functional algorithm to a vector of objects, trying to manipulate some member variables or call a member function, you would know that the result is so hideous that it isn't even worth considering. There is a reason people prefer iterative solutions; they are how the real world works. Reality is algorithmic, not functional, and so are user specifications for the things they want done. Trying to cram them into an abstract mathematical functional model is insanity.

    > Use, carefully, and always when possible, smart pointers.
    > Remember std::auto_ptr is your best friend

    Most of the time, no. While I would not deny the utility of auto_ptr in localized situations manipulating the object state during reallocation, its constant use indicates lack of understanding of object lifecycle in the program. It is fashionable in Java to create objects left and right, without consideration of who is supposed to own them. Hey, just let the garbage collector take care of it! Who cares how long the object lives? Obviously, such immature mentality produces plenty of memory leaks for which Java is so infamous. In a good design object ownership is strictly defined. Objects belong to collections that manage their lifecycle. There ought to be no "dangling" objects that just "hang there". If you don't know to which collection the object belongs, you have no business creating it. If you think your objects are "special", you haven't thought beyond their internal functionality or considered where it fits in your overall design.

    > Question 2: How can I actually implement such a decoupling?
    > I would use a simple, socket-base, take-my-data, gimme-my-results scheme

    And thereby slowing your program to a crawl? There is a reason people use CORBA and the like: those frameworks optimize distributed object calls to avoid network hits, often being able to reduce the overhead to be equivalent to a virtual function call. Furthermore, networked applications have their own set of complexities and security considerations. You get to keep an open port somewhere, handle authentication (becase wherever there's an open port, there will be malicious connections), and extensive data validation (for the same reason). While these problems are applicable to dis

  259. Re: cycle by Anonymous Coward · · Score: 1, Informative
    The term "cycle" in the GP post refers to a loop of references.
    a->next = b;
    b->next = a; /* objects 'a' and 'b' will not be freed unless you break the cycle */
    He's saying that if you have cycles then your memory will not be freed, and that could result in a crash when you run out of physical memory.

    See also: wikipedia article on reference counting.
  260. Taming C++ by angel'o'sphere · · Score: 1

    There is a book, called Taming C++ from Jiri Soukoup.

    A lot of stuff in the book is likely not interesting or even strange, but he has excelent ideas about data structures.

    E.G. if you have an aggregation (in terms of UML) in Taming C++ the suggestion is to implement it as double linked list which is inherited via a template (kind of mixin).

    Try to find it in a library, look over the chapters and look at the code examples regarding that (and skip everything regarding design patterns ;D )

    Writing code like it is suggested in the bug is makes it very resistant against memory errors and the code is ultrafast!!

    angel'o'sphere

    --
    Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
  261. Memory Checker (e.g. Insure++) & Defensive Cod by Anonymous Coward · · Score: 0

    Get yourself a good C++ memory checker like Insure++. Code defensively and test extensibly with the memory checker prior to deployment.

    By code defensively I mean things like the following:
    - If possible use string routines that verify the length is not overwritten. Insure++, etc. won't find problems unless they occur during your runtime testing.
    - Code using data structures and malloc as needed. Don't assume you will have a maximum number that could cause memory to go out-of-bounds.
    - Code in alerts to inform you if a structure is getting too big (e.g. memory is not being freed).
    - Don't assume data being read from a file or passed in from another program is of the proper type. Always check to verify and alert if there are issues.

    For the memory checker, enable warnings & errors and do as much testing as possible to remove any problems. The software can find memory leaks, accesses to bad memory, arrays / strings / etc. that go out of bounds, etc.

    Once you get the hang of the software, you can write rock solid code...but remember to code defensively so you learn to write good code and catch things the checker software doesn't. Don't rely just on the checker software.

  262. QuickCheck by Paul+Johnson · · Score: 2, Informative
    Try using something like QuickCheck . The original version was for Haskell, but you could easily adapt it to work with C++.

    The idea is simply to define the "space" of legal inputs for each module and the correctness criterion for each input, and then generate random inputs based on the spec. This is far more effective than traditional hand-coded test data at both unit and system test levels, and as an added bonus the test spec doubles as a formal specification of the correct behavour that coders can actually work from. This is similar to the XP practice of "test-driven development".

    Paul.

    --
    You are lost in a twisty maze of little standards, all different.
  263. Easy! by Anonymous Coward · · Score: 0

    Make a compiler (or translator, converter, or whatever you prefer to call it) in {Haskell,Lisp} translating {Haskell,Lisp} into C++. Then, make your application in Haskell and let your compiler spit out C++ code.

  264. C++ is NOT up to the 'task'! by Anonymous Coward · · Score: 0

    One word, Bubba!

    Ada. It's the ONLY way to create truly safe software.
    Trust no others.

  265. Memory and state... by segfault_0 · · Score: 1

    If found the biggest problems that cause crashes are memory management, lack of testing and object state issues.

    Doing things like ensuring that an object allocates its own memory and deallocates that memory in a well managed fashion in every possible instance is a good step. Also people developing object oriented code in C++ often dont think about the state of their objects and instead assume proper usage, this is a *big* mistake. You should ensure that your objects are always in a valid state no matter what happens or throw an exception, every constructor and method; and expose as little member data to unmonitored changes as possible.

    Finally, ive found unit testing to really be useful. Every class, or if needed group of classes, that i develop gets a unit test module that fully exercises its functionality, focusing on boundary conditions. No program is crash proof but if you write your software well and test each piece and then the pieces together, you can have some reasonable assurance that things will work as expected. A well defined test suite for after you put it together doesnt hurt either.

    --

    I was crazy back when being crazy really meant something. (Charles Manson)
  266. How to write ultra-reliable software by CapnFreedom · · Score: 1

    First, there is no magic solution to this. IT IS A LOT OF WORK. Also, my company predominately develops software for non-Linux platforms, so I'm not going to recommend any Linux specific tools.

    I recommend the following (by no means a complete list):
    1. Fuzz testing
    Fuzz testing is throwing directed yet random inputs at a program to see how it fails. Extremely long strings, null terminated strings, invalid files, files that are "almost" valid, etc. It's good for security but it also helps reliability. Even if all your input comes from trusted sources, by protecting against invalid input you also protect against bugs in these sources.

    2. Dynamic Analysis Tools
    There's a wealth of tools that'll simulate disk-read errors, out of memory errors, and other failures like this. Even if you expect to always have enough memory, OOM conditions may happen even temporarily. Tools like AppVerifier help detect heap buffer overruns, underruns, and bad API usage. Run your test passes under tools like these.

    3. Static Analysis
    There's a host of tools which can analyze source code and look for problems. Run these as often as possible and fix all the issues which come up. If they are quick to run, make a clean run checkin requirement.

    4. Establish a feedback loop
    Even with the strictest coding standards, strict testing, and excellent tools, crashes will happen. Eventually, your code will run in an unexpected environment, some external influence on the program will corrupt its environment, or some maintenance coder two years down the road will checkin a "fix" that introduces a crashing regression for some customers. Have someway for your customers to send you dump files whenever a crash does happen. If you happen to support Windows, this is really easy. Microsoft has a site for getting access to all the crash data that the customer would send for your product. Establishing an account is free (as in beer), but does require you to provide a VeriSign ID to establish identity, so noone else will try to get at your data. My company uses this, and it allows us to focus on the top N crashes that occur in our products so we get the most bang for our bug.
    Even if you do all of the above, there will still be some crashes in the product.

    What not to do:
    1. Swallow all exceptions
    This'll make your code appear more stable on the surface, but by blindly swallowing exceptions you are forcing your code to operate in a state you never designed for. All you really do is turn an easy to diagnose crash into an impossible to diagnose crash, or worse, a bug that just results in silent data corruption.

    2. Believe that using library x/Java/.Net/STL/etc. will fix your problems
    All of the above are just tools, but it is still possible to have crashes even if you use these tools 100%. An OOM exception in any of the above is more graceful and more recoverable than an access violation, but you're still going to have to do a lot of work to make sure you eradicate the sources of exceptions in your code as well as make sure the exceptions you do expect and can recover from you can actually rollback/retry/etc. to leave your data in a valid state.

  267. You're screwed - the libraries will get you by alispguru · · Score: 1

    Sadly, the programming language cannot be changed due to reasons of efficiency and availability of core libraries.

    I can all but guarantee you that said libraries will have undocumented memory usage "features" that will conflict with whatever careful programming model you put together in your code. Very, very few C++ libraries are designed with long-term memory usage sanity in mind. If I were you, I would not trust any code that I hadn't read in detail.
    --

    To a Lisp hacker, XML is S-expressions in drag.
  268. Re:I don't know why this dominates the first page. by Wolfier · · Score: 2, Interesting

    I'm sorry, but I just can't agree. It might appeal to a mathematician who wants to see everything use functional notation and hates every language except lisp, but to a non-abstract-elite-ivory-tower-mathematician this is absurd. cin is not an array of integers and the use of the adapter obfuscates the fact that you are using a conversion from a char array to an int. The back_inserter also makes it harder to see where the data is going by losing "v" in it. Many would also frown at it for taking a non-const reference, although since it is a standard adaptor it is probably ok


    Not understanding something is one thing, but not understanding something so let's reject it as being "elite-ivory-tower" and "academic" is another. I've seen a lot of buggy C++ code being rewritten employing this style in obvious places - many defects were automatically addressed.


    Reality is algorithmic, not functional, and so are user specifications for the things they want done. Trying to cram them into an abstract mathematical functional model is insanity.


    I disagree. Reality is reality. Algorithmic or Functional are just ways people look at it. Aren't "algorithmic" also abstract? Isn't "object-oriented" abstract as well?

    By the way, using your vocabulary, I view the world as a mixture of "algorithmic" and "functional". No pure anything can describe the world, in my opinion.


    Reality is algorithmic, not functional, and so are user specifications for the things they want done. Trying to cram them into an abstract mathematical functional model is insanity.


    Being functional or algorithmic has *NOTHING* to do with one being "more mathematical" and the other "less mathematical". I advise you, that your use of the common peoples' fear for mathematics in your arguments is not going to help.


    C++ programmers are often unnaturally attached to efficiency and have to be watchful for template bloat. Your copy generates 88 instructions, whereas an equivalent iterative solution is only 33 instructions long.


    Templates, being code generators, differ by nature to hand-tuned codes. So your code generates only 33 instructions vs the template's 88. Great - now tell me - which architecture? What compiler? What version of that compiler, and whose STL are you using, and which version of THAT?
    And before you count the instructions, did you realize that this code is waiting for keyboard inputs, therefore what you're doing is unnecessary (and obviously premature) optimization?


    While I would not deny the utility of auto_ptr in localized situations manipulating the object state during reallocation, its constant use indicates lack of understanding of object lifecycle in the program.


    How does the constant use of auto_ptr relates to the understanding (or the lack thereof) of object lifecycle? Sorry, but understanding object lifecycle the liberal use smart pointers are not mutually exclusive.


    It is fashionable in Java to create objects left and right, without consideration of who is supposed to own them. Hey, just let the garbage collector take care of it! Who cares how long the object lives? Obviously, such immature mentality produces plenty of memory leaks for which Java is so infamous.


    It is fashionable *among incompetent* Java developers to create objects left and right which make their programs memory hogs. It is also fastionable for *incompetent* C++ programs to forget deallocations leaking memories. What's your point? This mentality, immature or not, is not unique to managed languages.

  269. Use Erlang as a model by Isosceles+Kramer · · Score: 1

    You may want to take a look at Erlang before getting started on the project. Erlang is a functional programming language that already addresses fault-tolerance, modularity, distributed computing, and other problems you may need to solve. Even if you don't end up using Erlang, you could probably pick up some good design ideas from the (excellent) documentation.

    Erlang does provide several mechanisms for interfacing with C code. If you wanted you could use Erlang at a system level, and C++ at a lower level where performance and interoperability with existing code is important.

  270. Plan on failure... by Anonymous Coward · · Score: 0

    Large clusters are in a constant state of failure. Plan on having at least one node down (due to failed hardware) at any given time.

    Some techniques to live with the state of failure are as follows:
    -Error detection (know when a node is giving goofy results)
    -Failure detection (know when a node has died)
    -Checkpointing (periodically saving each node's state in a 'recoverable' manner)
    -Hot spare nodes! (So your N-node computation can keep going after losing node(s))

    If a node is either failed, or providing inconsistant results, then remove it from the cluster, and assign a hot spare. Restore to the last checkpoint & resume your computation.

    Failure happens. Plan for it.

  271. Some ideas for you. by Anonymous Coward · · Score: 0

    Hi there,

    First of all, I want to ask you to have a more open mind about all of this. You sound like you have already decided that using a particular language will result in poor software. I can reassure you, though: If you are using C++ properly and have written all your code perfectly, your program will not crash. It really is that simple. :-P

    Leverage as many tools as you can to help you deliver quality. Valgrind, memcheck, gdb (I like the ddd shell), whatever it takes. Look into commercial tools as well.

    Establish good unit testing practices, code standards, peer review, and QA procedures. Find a development process that will fit your organization and use it. Make all of those things work for you.

    Finally, learn to use your tools as well as you can. Stop blaming the knife when it cuts you. Instead, keep it razor-sharp and learn how not to cut yourself with it. It does not matter what kind of knife you are using. Make the commitment to craftsmanship that's required to deliver quality software.

    Okay, off the soapbox and on to some practical ideas for you to investigate.

    First of all, use a high-quality, modern C++ compiler and the best libraries you can find. I recommend you explore Boost, to start with. If you want garbage collection, use a garbage collector. Have a look at the commercial garbage collectors or the Hans-Boehm garbage collector. Remember that memory is only one resource that you will have to manage, so be sure to look at the smart pointers in Boost and the standard library, and learn to use RIAA in the right way.

    You didn't mention the kinds of algorithms you needed, but if they're mathematics-related, check out Blitz++, POOMA, MTL (Matrix Template Library), GNU mp, fftw, ... and, well, you have Google. ;> But thos are all good ones.

    For distributed computing, components, object persistence, and many other very cool things, I suggest that you take a good look at Ice from ZeroC Software ("http://www.zeroc.com"). In my opinion, it's got all of the great things about CORBA only much, much nicer to work with. It supports the platforms that you mentioned and several different mainstream languages, and is very stable and efficient.

    GUI: Qt. Or, find another library you like. there are lots of good ones that should meet your criteria. You will get the most versatilty from whatever you decide to use by
    using the GUI library well and building to a good, modular design.

    Finally, unless there is some reason not to do so, don't forget that you can easily bind C++ into some other language. You could write parts of the application in Ocaml, Scheme, Ruby, or whatever else you want.

    Best of luck to you.

  272. Re:"3. NEVER ASSERT!!!!" ...? by TemporalBeing · · Score: 1
    I really think you had better qualify this. IMO, assertion failures do not *cause* problems; they are messengers, and the message is always this: "Your program is broken." I don't think you want to *recover* from a broken state. I think you want to debug it -- find out what went wrong, fix the code, recompile, test, and re-deploy.


    It's very simple - don't use assert as assert will just crash the program. Rather, do something better. Detect the error, give the user a good and useful error message, and then terminate the program. You can't do anything else, but at least you can give the user some idea of what happened - of what went wrong - and you can give yourself a good idea where to look to debug it. And, BTW, nothing else in the system can produce a useful message to the user. Life would be a lot easier if everything in an OS did that. (Sure, a core dump helps the developer too, but it won't help the user know what happened, and it won't be very meaningful.)

    Asserts just produce crappy software - and BSOD's.
    --
    Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
  273. My Top Ten by dubl-u · · Score: 2, Informative
    THere is no silver bullet for what you describe other than sound development practices. The best results in this area are acheived by teams who are constantly refining their processes based on lessons learned in previous software iterations.

    Bulletproof code isn't cheap, but it can be done.


    This is the most insightful comment I've seen so far. Particular tools can fix particular problems, but that's the easy part. The hard part is finding and noticing the problems, so that you know to look for (or make) the tools.

    My teams have in-production bug rates well below one per developer-month. Here are the ten things I think are most important:
     
    • test, test, test (manually) - The only way to be sure that something works in production is to repeatedly and frequently prove that it works in conditions as bad or worse than production.
    • test, test, test (automatically) - Write unit tests, integration tests, end-to-end tests, and load tests. Write as many as you can in test-driven development style, where the test comes before the code that makes the test pass. My code bases are circa 50% test code, with 95% code coverage.
    • make testing the default - Make your tests run with one simple command. Then automate it so that all tests run on every checkin.
    • integrate frequently - Keep your colleagues up to date: check in every few hours. Breaking your work down into discrete bites takes practice, but it's worth it.
    • work as a team - Get everybody in one war room. Make it a great environment to code in. A big source of bugs is misunderstanding, and having everybody together eases intentional communication and creates a lot of tacit communication.
    • code in pairs - Yes, this takes some getting used to. But pair programming is just cranking up code review. Now that I've gotten used to it, I think solo coding is no fun: I know I'm making stuff that's less good than it could be, but until I come back to it a week or a month later, I can't tell what the problem is.
    • work sane hours - Once you start doing these other practices, you will discover that there is no point in staying late: as productivity drops and your error rate increases, marathon sessions just dig the hole deeper. Drunk drivers think they are just fine; so do tired coders. Both are wrong.
    • regularly look back and ahead - Every Friday at 4, bring in cold beers and talk about what went well and what didn't. No need for action plans or GANTT charts; just talk.
    • aim for perfection - A lot of shops consider it perfectly normal to have hundreds and hundreds of bugs in the database. This may be normal, but it's not necessary. There are a number of teams working at or below the level of one bug per developer-month, and yours could be one of them.
    • remember: quality can pay for itself - I have seen shops where developers average 50% of time in the debugger, and then complain that they have no time for code reviews and unit testing. Even if they can't connect the dots, you can. I spend perhaps five minutes a day in the debugger, and every time I do it, it's a sign that I'm missing a test and that the design could be clearer.
  274. Re:I don't know why this dominates the first page. by Anonymous Coward · · Score: 0
    Use and abuse the STL.


    Crack smoker.
  275. Recently did just this by ozzee · · Score: 1

    We used C++, no other language could match the portability and performance requirements. (Windows, Linux, MAC)

    The system we built is a P2P real-time communications system layered over TCP/HTTP and UDP of which we implemented a virtual file system for sharing files as well as data streams (telephony and streaming video/audio).

    The performance was needed becuase of the need to minimize the number of root servers we need and the stability is required because the clients run for hours and hours and crashing is not an option.

    We used smart pointers for everything that is dynamically allocated (either reference counted Austria C++ smart pointers or std::auto_ptr).

    We wrote our own serializer/deserializer (which took about 3 days to write) which uses standard C++ and does some pretty clever type safety (hard to serialize somthing you're not supposed to be able to - in fact you get compile-time errors). As an aside, all the libraries we wrote follow the "catch errors in the compiler if you can" rule, making it harder to write broken code.

    Virtually everything has a unit test (using the Austria C++ unit test environment).

    Automated builds and tests. We have 2 machines that continuously build and test for Linux and Win32. Often we find errors in the code that only show up in one of the builds but the error is truly a problem in the other system as well.

    There are a whole bunch of other things we do as well but these are the ones that get you 80% of the way.

  276. Idea!! by advb89 · · Score: 0

    Oh, I know!! Model it after Microsoft Internet Explorer!!!

    --
    <overrated>Insert Sig Here</overrated>
  277. ...and the answer is 42 by Anonymous Coward · · Score: 0

    What a stupid question.

    Its either a complex problem, whereby no amount of threaded dribble will help, or trivial enough that the author should put his head down and work it out for himself.

  278. Try GCJ. by Anonymous Coward · · Score: 0

    (The GNU Compiler for Java, I mean.)

    Lets you write your logic stuff in Javur, compile it to native code with all of the benefits of managed code (except dynamic optimization) and interface some C++ in once you start getting spots where near-managed languages aren't enough. It's what we use in our company's core business functions and it hasn't failed us yet. You can even use SWT to get nice, GTK+-ish GUIs. And then there's JUnit.

  279. Oh, and by the way... by Hurricane78 · · Score: 1

    ... I *do* like ocaml. Especially as a replacement for C/C++. So i'm even planning to use it for games (has opengl and sdl support.)

    But every language has its purpose. And ocaml is more targeted on a fast next-generation language for everything, while haskell wants to be the perfectionist.

    And i guess this job is a perfectionist's job.

    Use Ocaml where speed really matters and C is too outdated for you. ;)

    --
    Any sufficiently advanced intelligence is indistinguishable from stupidity.
  280. Ultra Stable, Crash-Free C++? by GodLived · · Score: 1

    ... after reading the opening line, I'm ROTFLMAO, SCOOMN (spitting coffee out of my nose). No kidding. I had a mouthful of coffee, now I have to clean off my monitor and keyboard.

    Ultra stable... crash-free... rhetoric of the "zero defects" camp. Ooops, Service Pack 2 is ready to install, gotta run.

  281. Ultra Reliable Code by oldCoder · · Score: 1
    I have written some ultra-reliable code. Careful design and coding followed by a great deal of testing assisted by automation.

    I have recently become a fan of test-driven design and recommend the discipline.

    If you can use GC/managed code, then go for it. At least in those parts where you can. Memory mis-management is an important source of errors.

    Get help with testing and with regression testing.

    --

    I18N == Intergalacticization
  282. Recommended Reading by Anonymous Coward · · Score: 0

    C++ Coding Standards... by Herb Sutter. This book is a summary of other fine books. See them for details.
    Effective C++ by Scott Meyers
    More Effective C++ by Scott Meyers
    Effective STL by Scott Meyers

    Check out http://boost.org/

  283. Check out ACE by H0p313ss · · Score: 1
    Check out the The Adaptive Communication Environment it does a lot of what you need to do, it's rock solid and had been deployed in a number of military and avionics applications.

    From the overview:

    The ADAPTIVE Communication Environment (ACE) is a freely available, open-source object-oriented (OO) framework that implements many core patterns for concurrent communication software. ACE provides a rich set of reusable C++ wrapper facades and framework components that perform common communication software tasks across a range of OS platforms. The communication software tasks provided by ACE include event demultiplexing and event handler dispatching, signal handling, service initialization, interprocess communication, shared memory management, message routing, dynamic (re)configuration of distributed services, concurrent execution and synchronization.
    --
    XML is a known as a key material required to create SMD: Software of Mass Destruction
  284. You're on the right track with modularizing... by Anonymous Coward · · Score: 0

    I managed a project with similar requirements, and ended up using separate modules that communicated with each other to isolate the effect of bugs causing crashes. I had the advantage of using a message passing microkernal architecture (qnx), so the IPC was easy and stable. The two most sigificant advances I made: 1) addinng code to the base library compiled into each project to capture all traps (bad ptr, illegal instruction, etc) and write the call stack and memory dump etc. to a log file before dying, 2) wrote a monitoring program that detected a "dead" program, logged it (and paged me), and then restarted the program (along with alerting the operators of the system to expect a glitch). This way, every time a once in a month type bug occured, everything was logged and I could easily track down what exact line carped and what conditions existed to enable it. In later years, I ported the entire codebase to windows, by creating an emulation layer of the IPC functions. The result was a near crash-proof package, which could be distributed to different clients, but this took several years to achieve. There was also a lot of simulations done in house before shipping to customer site, to locate problems before they happened in the field. So: yes, modularize, use IPC, add a monitoring program, and build self-diagnosing routines into all the programs, that call home and "bug" you to fix them...

  285. Opposite Advice that _WORKS_ by IBitOBear · · Score: 1

    I have written a lot of code with very stringent uptime requirements, and I have some advice that is going to be backwards compared to the advice of others. But you have to take _all_ this advice as one truth for it to work for you.

    1: Use the heap. A lot. The heap is your friend. Virtually every overrun exploit and crash involves the stack. It's not that you "can not" overrun something and bone yourself on the heap, it's jsut that you tend not to. Really. See number two below

    2: AUTOMATE your heap. I use reference counted handles to target objects. Not "auto_ptr", but real live, honest to goodness, refrence counting. I spend/spent the time to come up with a bullet-proof Handle class TEMPLATE and then I _use_ it.

    3: Virtual Distructors. I'll say it again, VIRTUAL DISTRUCTORS. If it has the word class, it has "virtual ~" in it somewhere. Every class, every time. Not inline either. The cost is miniscule, most implementations will be helped by this either in the vtable or the heap management or the code generation, and if you are following rule 1 and 2 and you are doing _anything_ right in your design (e.g. encapsulation and inheretance) this will lead to natural solutions to the +/-2% problems of final integration.

    4: THREADING. Use it. It is easier to write N small programs that block on their inputs than it is to balance or maintain an N-way poll/select environment. If you don't use threads you will end up with a hell-a-painful switch-case statement somewhere in the core of everything, and that way lies pain and madness.

    5: Recursive Mutexes. The standard pthread_mutex et-al is not recursive, but a simple class wrapper which checks ownership and increments counts can make it so. With recursive mutexes, and an agressive locking policy you will find that you will not make mistakes.

    6: The "automatic Lock_Object". The Mutex class should only be takeable/lockable by a companion LockObject class, and _these_ should always be automatic (stack based). The (recursive mutex) lock is taken in the constructor and returned in the (virtual) destructor. It's the law. It will make your life better.

    7: _Use_ EXCEPTIONS. People spout all sorts of garbage about when "NOT TO" use exceptions. They are full of "it", and then never tell you when _TO_ use them. The simple answer is.... this: Make a directed graph of your code _state_ dependencies [for each thread] in (aproximate) call/execution order. Weight the dependencies and restructure the graph so that the most necessary paths form a strict tree. Now the "edge and corner cases" will appear on this tangled-tree as cycles (loops). These loops should be cut open with exceptions. Start with a "class Fault" and then make sub-classes for each kind of fault (locking, logical, semantic, external [q.v. dropped connections]) and then *ALWAYS* use these exceptions for (and _ONLY_ for) backing up the central dependency tree.

    The net result is a "process space" (memory image, whatever) of shared state, composed of a set of self-sufficent threads.

    [ASIDE: the short version is "don't be afraid of your language, leverage it.]

    This is not the advice some others would give you. It does, however, work quite well.

    I have used this approach on several mission-critical projects and produced programs that were both "sufficently fast" _and_ maintained continuous heavy-load runtimes in the multiple-months-without-stopping quality of service range.

    --
    Innocent people shouldn't be forced to pay for inferior software development.
    --"Code Complete" Microsoft Press
  286. Did ANYBODY... by wrfelts · · Score: 1

    remember to bring their flame retardent suits before answering this post???

  287. WHOA BUDDY by C0llegeSTUDent · · Score: 0

    be very wary of C++ constructs that might result in a whole load of code being fired off behind your back...

    Did anyone else read this and think to themselves this guy is using WAY TOO MUCH FIGURATIVE LANGUAGE for c++?

    1. Re:WHOA BUDDY by Duhavid · · Score: 1

      No, no one else did. Just you. :-)

      --
      emt 377 emt 4
  288. Hire a software engineer? by po8 · · Score: 1

    How about hiring a trained professional software engineer? Trained professionals know about the various kinds of security and reliability risks, and have a grab-bag of tools for dealing with them. They also know a lot about how to deal with programming languages and environments.

    From your question, you appear to be in over your head. Get professional help.

  289. Re:I don't know why this dominates the first page. by Chemisor · · Score: 3, Insightful

    > Not understanding something is one thing, but not understanding something
    > so let's reject it as being "elite-ivory-tower"

    I did not say I did not understand it. I said I did not like it. I do not like it because it does not fit with the reality of computer operation, as discussed below.

    > Reality is reality. Algorithmic or Functional are just ways people look at it.

    On the contrary, you can see reality being algorithmic. Things happen one after another. To type "algorithmic", you depress a, l, g, etc. in order; you don't declare a set of letters, fill it with appropriate values and throw it at the computer. When you receive a specification for your program, it will say something like "get this from the user, then do this, then do that, then print out the result". No specification is ever written in functional notation outside the academic world.

    More importantly, the computer itself works algorithmically. It does one thing, then another. No computer has ever worked functionally, and no computer ever will. All of them will decode and execute a sequence of instructions, and if you refuse to write your code likewise, you're only adding translation overhead.

    Even in the hallowed halls of science overuse of the functional notation creates serious problems. The entire hodge-podge nonsense we call quantum mechanics stems from the attempt to describe a complicated system as a function. Instead of trying to get a set of time-value maps for the whole system, it would be more appropriate to look at the system's constituent parts and algorithmically simulate them through time. That way you wouldn't get any "spooky action at a distance", stuff being there and not there at the same time, and all other equally ridiculous denials of reality.

    > I advise you, that your use of the common peoples' fear for mathematics
    > in your arguments is not going to help.

    I wasn't using that argument, but, now that you mention it, it is a reasonable one. Most programmers couldn't care less about higher mathematics, and, even if they were forced to study it in college, they likely have forgotten it all by now. Computer algorithms require minimal mathematical background. The most I ever used was a bit of calculus to write scan-conversion routines. So, whether from lack of practice, or from lack of interest, most programmers will prefer you didn't drag them into the world of useless mathematics. (and I use the word literally here)

    > Templates, being code generators, differ by nature to hand-tuned codes.
    > So your code generates only 33 instructions vs the template's 88. Great
    > - now tell me - which architecture? What compiler?

    That is quite irrelevant in this case. istream_iterator notation generates extra code for reasons that will not go away no matter how hard you try to optimize it. Yes, I might be able to write an istream_iterator that would have no overhead over my iterative version, but it will not be standard compliant. The istream iterator has to read on construction; it has to store the read value; it has to be constructed, since it must keep a reference to the source stream; it has to handle special cases, like the end-of-file, and the subsequent conversion to the end iterator value. However good you might be at optimization, you will not be able to discard these and still be compliant with the specification.

    Also, which compiler or architecture you use will not make all that much difference in the size of the compiled code. I guarantee you that your functional copy will never generate smaller code than my iterative loop, no matter what compiler you use or what architecture you compiler for. There is a certain amount of work to be done, and my version does less work. It is as simple as that.

    > And before you count the instructions, did you realize that this code is waiting
    > for keyboard inputs, therefore what you're doing is unnecessary (and obviously
    > premature) optimization?

    First, you should note that I

  290. Use a different language by jopet · · Score: 1
    I know you shortly said that is "not possible" but I am not convinced about the reasons you gave for this. If you want a program that cannot segfault choose one that prevents segfaults at compile time. Such languages exist, e.g. take a look at OCaml. Also, if your project is modular, identify the parts where stability is absolutely essential. Maybe you can use different solutions for different parts.


    C++ is such a terrible language that there is simply no way to get anywhere close to what you want without extremely high cost (both time and money).


    Use a strongly typed language with built in memory management to solve your problem. In my experience OCaml gives you all that. Once you have learned the language and the concepts implemeted in it, C++ will appear to you anachronistic and ridiculously messed up. Ocaml does provide a nice set of librabries, but you can also use C/C++ libraries via its native language interface (though this introduces risks and of course, the libraries might still crash).


    In any case, reconsider the language choice -- it is really quite essential especially with regard to segfaults and similar issues.

  291. Advice on C++ API by smoker1967 · · Score: 1

    I would honestly recommended ACE and TAO frameworks for all kinds of C++ projects. I'm not salesman and it's free software, just (from my 15 years with C++) this IS my software of choice. Start it here http://deuce.doc.wustl.edu/Download.html/ or Google for ACE+TAO

  292. Re:Nonstop Kernel: none of the above by tjanke · · Score: 1

    For a really good look at the history and early design of Tandem computers, see this wikipedia article: http://en.wikipedia.org/wiki/Tandem_Computers.

    In brief, the Nonstop Kernel is none of the above. It's a proprietary OS, originally written from the ground up by Jimmy Treybig and two other ex-HP engineers. It has a loosly-coupled, message-based architecture, designed with reliability as its primary focus. It runs on proprietary hardware, also designed with reliability as its goal.

    When HP expressed no interest in this new high-reliabilty, high-availability computer that three of their engineers had designed, those engineers quit HP and founded their own company, Tandem Computers, around 1974. The name came from the design of the platform; the minimum system you can buy has two processors and two (mirrored) disc drives (the maximum has 4000+ processors); processes run in pairs, with data checkpointed from the primary to the backup, so that if a process or cpu fails, the backup can takeover immediately and continue processing. Failover time is typically less than 15 milliseconds.

    True story: a data center where I worked had half Tandems and half Amdahls. The building got hit by lightning. The Amdahls all went down, and took three days to get back up. The Tandems lost half their processors and a third of their disc drives, and kept right on going. Processing continued with nary a pause, and no data was lost. It was amazing to watch.

    Tandem had revenue of $1.9 billion; the reason you never heard of them is that their target market was never consumers. The cheapest machine was in the $millions circa 1980, and about $250k circa mid-nineties. They built enterprise-level machines for transaction processing that would almost never go down (some units have run in the field 24/7/365 for 5+ years with zero downtime), and they sold to banks and stock-exchanges and telephone companies. Most of the world's financial processing infrastructure runs on Tandems; almost any financial transaction you make, anywhere in the world, e.g. withdraw money from an ATM, buy gas using your debit card, buy or sell stock, etc., is processed on the backend by a Tandem computer.

    In 1997, Compaq bought Tandem. In 2001, HP bought Compaq, and with it, the Tandem division. Tandem computers are now called HP Nonstop computers. Full circle.

    --
    Cheers, Tim -- Tim Janke Part mad scientist, part lion tamer: sr. software engineer, global team leader, project mana
  293. Isolate everything dangerous, test ALL inputs. by zCyl · · Score: 1

    The responses are flooded already, but just in case you're reading far down, I'll add my two cents. Use the tips mentioned, but the central most important key is to isolate all the dangerous aspects. C++ has a lot of features that can trip you up with subtle errors, like arrays without boundary protection, and pointer access. So take all of these features, and isolate them to a very small set of very simple functions, and use those functions repeatedly. If everything dangerous is isolated into simple functions that are used repeatedly, you will eliminate a large part of your error by shielding yourself from the problems. You'll be adding a bit of extra overhead, but real stability requires a little extra overhead.

    Once you've done that, make sure you test each component separately. Every piece of the program should be tested with a test suite of inputs designed to test its range of outputs, and test its resilience against outputs which are out of bound. Every single component MUST test its inputs, and must have a prescribed action for any type of faulty input, EVEN if that faulty input is "impossible" in your design. A large percentage of crashes are due to high level assumptions about inputs that are made invalid by other sections of code, where the developer, or another developer, is no longer aware of the constraints, or writes a section which accidently generates an invalid input to a function. So as a result, handling invalid inputs inside every function needs to be one of your central focuses.

    If no portion of your program can cause a segfault because all pointer work and array accesses are isolated into protected functions, and if every single function has a procedure for handling invalid input and invalid object data for every piece of object data, then your program will not crash. (Unless you made a mistake, that is. Such is life.)

  294. A few key points by Peaker · · Score: 1
    My take on it:
    • Avoid any and all forms of code duplication (or the DRY principle in general). This may mean a lot of templates, code generation and even preprocessor use (unfortunatly, X-Macros are irreplacable in some cases, even with all of C++'s machinery). Sometimes there is no escaping a code generation script. This must be done, against all lazyness.
    • One of the worst source of bugs is parallelism and management of shared resources. Since knowing this, I have avoided them as much as I could and as such have little to say about debugging them properly. However, I would suggest reducing the amount and complexity of interactions between parallel threads and processes, even at the cost of performance when that seems reasonable. The amount of time spent debugging an ultra-optimized communication scheme is better spent optimizing other parts of the system.
    • Runtime debug traces. Spend time to create a mechanism for fast debug tracing. I was surprised to find out, that if you trace into memory and dump that memory to some device in big enough chunks, that tracing each and every function entry, exit, argument values and return codes is not expensive and has negligible effect on performance (Ofcourse you can filter out statically traces that cause trouble). If you use a system-call-per-trace, its not going to be fast enough. This relates to the former point of parallelism. You will not be able to kill the bugs without a very good and solid debug trace mechanism. It may be expensive to write as there are very few existing implementations out there, but if your project is large enough and employs parallelism, you need it, and you need it badly.
    • Consider all code production code, that must be reviewed (You do review your code..?), and make sure that any "hack" or lower-quality code is marked with at least a greppable //TODO and better yet with a #warning.
    • Error handling is just as important as the nominal case. Most developers write crappy error handling code at best, and ignore the error handling altogether at worst. Error handling should be written, reviewed and tested just like any other piece of code.
    • Write tests. A lot of tests. Get good coverage (>90%). To do all this, you will have to use a scripting language for your tests. Writing tests in a relatively low-level'ish language such as C++ is in my opinion a huge mistake. RAD-type development of tests which makes them more enjoyable to write and interactive to develop, in a language such as Python, will improve the quality and quantity of your tests by orders of magnitude. Python is a great choice for testing, and there are many tools for FFI that allow testing your C++ code from Python. The small effort to connect the two is worth it.
  295. RTFA by Anonymous Coward · · Score: 0

    Quoting:

    Now I know of several more transformations which I could have applied to my Scheme program before I translated it into C, which would have put mine in first place. A runtime profile of my program revealed that the majority of time was spent in the C routines "malloc" and "free." I could have eliminated that heap usage by transforming my program into a form in which all data allocation and control management would have been completely stack-based, with an explicitly managed stack. I could have pushed onto the stack exactly that control information which I deemed necessary. There were places where I could have modified the existing stack record, rather than popping it off and creating a (similar) new one in its place. These transformations were also presented in my Programming Languages course. Unfortunately, at the time that I did my Algorithms project, I did not yet grasp them well enough to use them well.

  296. Does that answer your question? by MikeOtown · · Score: 1

    well, does it?

  297. Sorry, *not* in C++ by HermanAB · · Score: 3, Interesting

    You cannot write highly stable code in C++, due to design flaws in the language. For this reason, the FAA doesn't allow C++ for use in aircraft systems. You can improve the situation with the use of a garbage collector though, but if stability and safety is critical, then you should use ANSI C. See this: http://www.hpl.hp.com/personal/Hans_Boehm/gc/issue s.html

    --
    Oh well, what the hell...
    1. Re:Sorry, *not* in C++ by landtuna · · Score: 2, Informative
      For this reason, the FAA doesn't allow C++ for use in aircraft systems.

      You might want to let them know about that.

      Aeralib

    2. Re:Sorry, *not* in C++ by HermanAB · · Score: 1

      OK, that's cool thanks! I'll read up on it.

      --
      Oh well, what the hell...
    3. Re:Sorry, *not* in C++ by Keick · · Score: 1

      also, the JSF project is 100% C++. Even had Bjarne help establish the guidelines. I myself am starting a safety-critical train control project, in C++.

    4. Re:Sorry, *not* in C++ by smose · · Score: 1
      For this reason, the FAA doesn't allow C++ for use in aircraft systems.

      Let's say that the FAA may not yet be entirely comfortable with C++ in aircraft systems.

      There was a paper or presentation that posited the question "Is C++ the natural enemy of DO-178B?" (I wish I could find a link for you, sorry). In particular, higher certification levels of DO-178B require more stringent proof that all of the software in the system has been exercised*. This proof is more difficult to attain when using exceptions, which can interrupt linear program flow. Templates are problematic in their own way -- for example, it can be difficult to prove that the whole template has been exercised against each of the types that instantiate the template.

      The FAA's slowness to adopt to ...uh... "new" technology is frustrating, certainly, but it's their job to be the anchor. The reliability of most desktop software is simply unacceptable for most in-cockpit applications.

      * Note: I had to run the structual coverage analysis on "printf" on one program, and that was only for Level C verification. You really are checking all of the code.

  298. Functional programming? by Peaker · · Score: 1

    This may sound like a troll, but it is an honest question.

    Seeing as all variants of Lisp support and even use not negligibly setf, setq, loop constructs and others, why is Lisp any more functional than Python, Ruby, or Smalltalk?

    If I had to classify Common Lisp with Python or with Haskell, it obviously falls into the Python class far more closely, and that's not really functional...

    1. Re:Functional programming? by YGingras · · Score: 1

      I'll bite.

      There are things pretty hard to do the functional way in Python. As an example if you wanted to get a sorted list of the foo for all bars you'd do:

          (sort (mapcar #'foo bar) :test #'>)

      but in python you have to use a temporary variable here and there which breaks an otherwise nice functional pipeline:

          foos = map(foo, bar)
          foos.sort()
          foos.reverse()
          return foos

      The lambda in Python is not quite right. You can't close over a writable var in it (in fact its really awkward to close over a writable in Python) and you can't use ifs and other statements in lambdas. Well we have a point here, why are there statements at all? In Common Lisp if is an expression and it has a value, that is the value of the branch that gets executed.

      You are right though, Common Lisp is not purely functional, and thats a strength. In CL you can use functional programming when the problem calls for it and OO when that makes you feel better. Yes you can express all loops as a tail recursion but there is nothing as good as while loop instead of pulling mental contorsions out of a hat.

      But there is more than just better functional programming that CL has (some implementations as least) and that Python lacks. There are macros, tail recursion, symbols, type inference, rationals, multi-methods and a syntax the easy programming a lot. Its really convenient to grab a branch of an if and to move it up in place of the if in only two key strokes. The indentation trick with python produce clean code but what a pain it is to play with blocks... and to grab that piece of code that happend to use two space per level instead of four.

      Yes, there is a problem with deployment in CL and Python wins there. The packaging system in Python is pretty neet too. And Python doesn't look too scary so you can start to do functional code even if you boss is an OO zealot. Norvig as a nice summary of the pros and cons of each language:

          http://www.norvig.com/python-lisp.html/

  299. It's not too hard. by Ivan+Matveitch · · Score: 1

    Design a language well suited to implementing your system, then write an interpreter or compiler for it in C++.

  300. Replace the memory manager by Ristretto · · Score: 1

    If what you want is stability, you must replace the memory manager. This requires no change to your code; there are several plug-in replacements. You can use a conservative garbage collector to get rid of memory leaks. Another possibility -- in the self-plug department -- is to use DieHard, which eliminates a wide range of memory errors and even defends against heap overflows and other heap corruption. Pick whichever works best for your needs, but pick one. You will not get stability and reliability with C++ if you stick with the default memory manager.

  301. ADA and C++? by Anonymous Coward · · Score: 0

    I actually used to maintain avionics software in a previous job, which is obviously extremely safety-critical real-time software. As you can imagine, it was designed to be ultra stable.

    It was written in ADA83, with a little bit of C thrown in for good measure (and to provide some fancy interfacing to other interconnected systems).

    I left that job a few years ago, and I now maintain software in an Air Traffic Control environment.

    It's much the same - the core is written in Ada, with C++ interfaces to the O/S (Unix). There's even a separate system which monitors the modules with a nice GUI front-end, and if one of the modules does happen to crash - it will immediately be restarted.

    In short - I've never worked on an ultra-stable software system that was NOT based on the ADA83/95 language.

    As for porting to Windows... are you 100% sure about that? For an ultra-stable platform? I hope this isn't safety critical software, where peoples lives could be at risk...

    Good luck!

  302. Formal Methods by Anonymous Coward · · Score: 0

    You must investigate this subject. Z, B-Method, ...

  303. MISRA by rreiner · · Score: 1

    It's pretty remarkable that in this entire discussion not one person has made reference to the MISRA guidelines, which are specifically designed to make it feasible to build highly-reliable systems in C (and now C++, although that is still work in progress), and which are backed by a worldwide community, excellent tools, etc. All the detials are at http://www.misra.org.uk./

    1. Re:MISRA by Anonymous Coward · · Score: 0

      MISRA subset is better than full C, but it still falls far from being the solution to the problem. The MISRA guidelines themselves contain several ambiguities, causing different MISRA compliance tools to analyse the code differently (and producing different results...)

      And as is stated in MISRA guidelines, the MISRA C subset is not really suitable for safety critical systems. Use some other language, like SPARK.

  304. As an added bonus... by game+kid · · Score: 1

    ...if null_functor learns D well (and|but) decides to quit (his|her) job, (s)he can make a kick-ass game with it.

    --
    You can hold down the "B" button for continuous firing.
    1. Re:As an added bonus... by cloak42 · · Score: 1

      I'm not sure whether I should thank you for pointing me to such an awesome game or damn you for pointing me to something that will waste SO DAMN MUCH of my time...

    2. Re:As an added bonus... by inter+alias · · Score: 1
  305. What are you willing to pay? by sadr · · Score: 1

    It isn't completely clear to me what you're trying to do.

    What is the cost/impact of a failure in your system? Are we talking a little bit of money (website), bunch of money (stock trading) or are we talking people dying? Or just your boss saying "I want 24x7 availability for this app darnit!"?

    I work on embedded systems using a limited dialect of C++ on safety critical systems. We, for instance, don't get to use dynamic memory allocation because it makes a system's behavior non-deterministic. (And besides, what do you do if you try to allocate memory and it fails?) Multi-tasking is just right out for formal certification of the application.

    Also, are you looking at high availability or high reliability? They're similar, and use some of the same techniques, but have different aims. In my environment, we'd rather fail and bring down a system than leave a system up that is producing even slightly incorrect data. (And we have a redundant unit in case of hardware failure, etc.) But in high availability, you want to keep operating, even if degraded. (Think telephone switches, where the ability to carry half the call with some static is better than nothing.)

    In general, however, you want as few components (both software and hardware) as necessary to do the job. Assuming a single system can handle the work, splitting it across three boxes just adds two more points of hardware failure, 2 possible communication failures, and a bunch of software to handle inter-machine communication. Every library, every OS call, and every component is a potential source of failure; use with caution.

    And in the end, if you really can't have failures, go look at formal development, certification and testing practices specified by the FDA or FAA. They don't guarantee it'll be perfect, but they give you an idea of the kind of work you need to get close. For example, testing that has MCDC code coverage of >90%. The cost will be an order of magnitude higher than for normal software, but it won't fail. And they have advice on use and certification of third party libraries and OSes. (Summary: Libraries verifiable to these levels also cost an order of magnitude more money.)

    Those methods will also give you advice on availability assessments of hardware, etc. Is an average server or PC sufficiently reliable for your application? This has to be one of your first assessments. (i.e. how quickly can you get hard drives replaced, and what's the simultaneous failure probability of 2 drives in a RAID/mirror setup?)

  306. Re:"3. NEVER ASSERT!!!!" ...? by neutralstone · · Score: 1

    I think we're working with slightly different definitions of the word "crash". When I think of a crash, I think of a program that was terminated not of its own volition, but by the operating system in response to, say, a memory segmentation fault.

    assert() is (usually) a macro, and you can define it to expand to whatever you want. By default, it usually expands such that if the tested expression is false, then exit() is called after some debug message (like "failure in foo() at line 1234") is sent to stderr.

    I *guess* you could refer to the call to exit() as a "crash", but to me it seems like deliberate behavior. In other words, the exit() call itself is not a sudden failure. The failure happened -- silently -- long before we got to the assert(). The call to exit() is done to limit the damage of the failure and to aid the programmer in debugging.

    Now, an assertion failure doesn't have to result in a call to exit(). It could result in a cute GUI pop-up window that says, "sorry it didn't work out; please fill out this form that we'll send back to the developers. Try to give as much relevant info as possible." And that could be sent back to the developers along with a core dump. A lot of developers have chosen this route, and it seems like a valid one. In a debug build, an assertion failure could instead result in a call to a function that pauses execution and launches an interactive debugger; this too is valid.

    But I think it's unhelpful to try to convince people that "assert will just crash the program" for two reasons: 1) assert() is only a messenger, and the programmer is always in control of how that message is to be delivered, because she always has control over the definition of the macro. 2) you're going against the writings of the experts, and if you don't qualify your meaning very carefully, you'll just end up confusing people.

    I think we pretty much agree in principle, but the definitions we're using are at disjoint. (That's a problem, because clear communication is very important in this business.) I think what you *meant* to say is, "don't use the default definition of assert because the default assertion failure action is to halt the program without giving much useful information to the end-user." That's a statement I can much more readily agree with.

  307. Simple rules by aminorex · · Score: 1

    Don't use new/delete or pointer arithmetic, and you're 90% of the way to crash-proof. Use STL and boost where you can. Pass references instead of pointers and let the stack manage your memory.

    Create processing units by forking, and communicate between them using unix-domain sockets. You can even handle network I/O in several processes this way, passing the socket file descriptor between processes through unix-domain sockets, if you need. For Windows the equivalent is named pipes, but you can't pass descriptors.

    --
    -I like my women like I like my tea: green-
  308. Oxymoronic - "Stable Software" and "C++" by Anonymous Coward · · Score: 0

    That is unless this is an application for helping maintain a barnful of horses.

  309. Helpful advice for any language by Anonymous Coward · · Score: 0

    I don't want to join the language wars so hear are some helpful design considerations for any language.

    Functions should do 1 thing and 1 thing only. This should be something that is testable outside of the context of the running system, if possible.

    Classes should control 1 complete and stand alone idea in the program and only one. This should be something that is testable outside of the context of the system, if possible.

    Well defined interfaces for the classes that are decided early. Changes to the interface will probably be necessary and should be communicated to all developers.

    Now everything might not be able to fit into this, but forcing yourself to think and implement in these terms does help to produce testable, straight forward, and simplier code than just banging away on the key board.

    The basic idea is to keep things simple and testable. Done right you can automate a lot of testing.

    Most importantly, Test early and test often.

  310. Safety critical systems by randyjg2 · · Score: 1

    *Sigh* Every year or two for the past ten years, I get into an argument with some European professor about the qualifications of American graduated students, Usually on their knowlege of engineering of computer programs.

    Thanks to this discussion, this year, I am going to have a much harder time defending them, I think.

    Safety critical systems is a branch of computer science, routinely taught in the better European universities. The book I first learned it from was Safety Critical Computer Systems http://www.eng.warwick.ac.uk/~neil/safebook.htm

    The field really got impetus after the Therac-25 failure http://courses.cs.vt.edu/~cs3604/lib/Therac_25/The rac_1.html
    where a group of people got radiated to death because of a minor (in a computer sense) error in some code, thus adding new meaning to the term "execution error".

    Its a vast field (google "safety critical") with large numbers of interesting published papers and few good books. I really can't remmend a current book, I haven't seen one I liked in years. I don't think you can learn it fast enough to be useful.

    You also need to know a fair amount of higher math to be really competant, or at least even understand whats going on... most of the true experts in the field apparently regard english as a required second language (Math being the first language, not that I can blame them, but often it is overused)

    The field seems to have suffered since the recession. and fragmented, but there is a good starting point at http://vl.fmnet.info/safety/

    It also seems to be rapidly migrating to India as well, because of the resistance of American "cowboy" programmers. This time, it is possible the game of "cowboy and indians" may end up with the Indian's winning, inasmuch as the techniques are going to be essential to the new multicore programming models. (I heard a rumor Herb Sutter is investigating that, but thats just a rumor. If so, however, he would be the person to talk to about safety critical C/C++)

    One of the techniques used in the field is formal verification. McGee and Kramer are coming out with a second edition of thier incredible book, Concurrency, http://www.doc.ic.ac.uk/~jnm/ early this year (last time I emailed them). The book is an gentle introduction to the field of formal verification and model checking, among other things. There are other books (a new one came out on the Spin Model checker, for example) but this is by far the most penetrable.

    Much more interesting is the use of model checkers behind UML or BPEL/SOA tools.
    Most of the really interesting stuff is still behind university walls, but tools should be appearing soon. I am trying to develop an open source grid based one but it's been slow going due to committments and resources.

  311. Re:I don't know why this dominates the first page. by Wolfier · · Score: 1

    I give you the rest - and I quite agree with your "train yourself to write smaller code" mentality.

    However..."Pointers must be owned by a specific object; created by that object, used by or through that object, and deleted by that object. That is the only way of ensuring that you always know when and where it is created and when and where it is destroyed, which is what I mean when I speak of object lifecycle."

    This is not necessary true in all cases.  For example, in a message-passing multithreaded environment, messages are often created by one object, passes through a message queue, and destroyed when a pool of thread, which often is part of another object, has finished processing it.

    However, you can view it as an exceptional case.  After all it's the exception that makes a rule.

  312. Solving your problem by Anonymous Coward · · Score: 0

    Use valgrind. It will tell you about memory access violations and can tell you what memory blocks have not been freed at program exit. This will get you 90% of what a good garbage collecting language will get you (the other 10% is, IMHO, not having to manually free memory blocks).

    For IPC: Keep it simple. Analyze your problem to determine if you can use something simple like message queues, or just file operations.

    Defensive programming: Assume system/c-lib calls will fail, and code appropriately.

    Multi-threading: This is a good way to make your program unstable. Avoid it if at all possible.

    GUI: I agree with the other poster: Qt is good. And it's portable across Windows and Linux.

    Windows: Get it running with no bugs on Linux first, then port it to Windows.

    I hope this helps you.

  313. Re:"3. NEVER ASSERT!!!!" ...? by TemporalBeing · · Score: 1

    I think we pretty much agree in principle, but the definitions we're using are at disjoint. (That's a problem, because clear communication is very important in this business.) I think what you *meant* to say is, "don't use the default definition of assert because the default assertion failure action is to halt the program without giving much useful information to the end-user." That's a statement I can much more readily agree with.

    While I can agree to that at least in principle, I would still not advocate using assert in any form or manner - it's just wrong so far as I'm concerned, and will for all intents and purposes not correct the behaviour that needs to be corrected - that is, telling the user what is wrong and handling it appropriately. The program should terminate as a last resort, after working with the user and the operating system to try to solve the problem.

    In referring to the term "crash", I mean any reason why the program terminated without completing its action - either because of a seg fault or because the program hit a point that was either (a) unexpected by the programmer (e.g. resource X did not actually get created) or (b) something didn't happen quite right, and the programmer decided to just quit without trying to figure out what happened - e.g. a lazy programmer.

    As per what to do about it, the program should so something like the GUI dialog you talked about, but tell the user what lead to the condition as well - for example, "Program X could not complete its operation because the operating system denied access to the Buffer Pool object while streaming file Y from server Z. Please fill out the information below to help the developers solve this problem.", and then send the information along with the core dump to the developers. Telling the user why the program thinks it has to quite in as much detail as possible (that the average user could understand) will help a long ways in not only debugging the program, and help desk - but also in creating a good perception of the program among your users, and they'll pleasantly be surprised that you think they're not as stupid as they really are, which will reflect well on you and your program.

    --
    Truth is like the sun. You can shut it out for a time, but it ain't goin' away. - Elvis Presley (source: imdb.com)
  314. More than one language by thatjavaguy · · Score: 1

    It might be appropriate to wrap up the C++ code in a CORBA/SOAP interface and use some other language to write the GUI.

    IME User interfaces tend to leak more than backend stuff because it's harder to unit test and effectively profile GUIS because of the seemingly random nature that some customers use the application.

    Beware of round tripping in Corba and Soap. They're what really kills percieved performance. We transfer a lot of data over Corba between a C# Client and Java and C++ servers and Corba is a very effective and efficient solution

  315. Re:"3. NEVER ASSERT!!!!" ...? by Anonymous Coward · · Score: 0

    You seem confused about the intended use of assert.

    It is true that assert should not be used to deal with user and system errors. That's not what it's intended for. Those kinds of errors should be handled by exceptions or error codes, and recovered from gracefully, if possible. An application should not die if the user types an invalid input into a form.

    Asserts are intended to handle programmer errors. Think of them as a programmer-defined extension to the compiler's and runtime system's checks. Typically they're used to validating programmer assumptions, such as those about: function argument values, internal data structures, and object states. For example: if part of the contract of a function is that it accepts only values between 0 and 100 for a particular parameter, it's the programmer's fault if it gets passed 102. It makes no more sense to "work with the user" on that error than it does to "work with the user" on the programmer's misspelling the function name, passing it too many or too few arguments, or passing it an array instead of an int.

    Another good use of assertions is blocking out "free" behavior, such as when a function or module is capable of more general behavior than you designed it for. Sorry to say: no feature is free. If you offer the functionality, you gotta test it. If you don't wanna test it, assert it out of your code.

    Of course, even assertions should attempt to exit gracefully: tell the user a problem occurred that was the programmer's fault, save their work if it hasn't been corrupted, and let them send an error report to the developer.

    I gotta say: once I started using assertions, I never looked back. It's rare I trip one of my own assretions, but when it happens, that's an hour or day of my life rescued from having to track down some ridiculous bug. Same story with unit tests. Both assertions and unit tests are layers of redundancy to help combat human error. Use 'em.

  316. Stable Development=Formal methods by Anonymous Coward · · Score: 0

    I would suggest looking at this:
    http://www.csr.ncl.ac.uk/vdm/

  317. Try this by Lazarus34 · · Score: 1

    We've used this with a good deal of success. And it meets all your criteria!
    ( Mainly C++ based, portable, distributed, multi-computer, multi-threaded, similar design methodology, etc... )

    http://www.connectivelogic.co.uk/

  318. Not Funny. by hummassa · · Score: 1
    > Well if this is beautiful, then why is it that I have no idea what it is doing?

    "Because you have no idea of what C++ is" would be my answer to that question. No offense meant, mind you, but IMO knowledge of C++ implies knowledge of the STL. Oh, I agree that your example is interesting (maybe
    array1.splice(3, 12, array2.slice(11, 2))
    would be better, but... there is no accout for taste, don't you think?
    --
    It's better to be the foot on the boot than the face on the pavement. ~~ tkx Kadin2048
  319. IMH?O by hummassa · · Score: 1

    > You say "IMHO" too often.

    Not really. In my post, I said IMHO every time I was stating an opinion rather than a fact (ie, twice) and IMH?O (once) when I thought my opinion about the beauty (and maintainability) of iterators can be construed as an expert opinion (programming in C++ since 1989...)

    --
    It's better to be the foot on the boot than the face on the pavement. ~~ tkx Kadin2048
  320. Re: Sorry, *not* in C++ and C by krischik · · Score: 1

    ANSI C for safety is critical software? Excuse me!

    First there is almost no true ANSI C avaliable today. Most of them are missing features like variant arrays or restrict pointers.

    And the C is about the unsafest language available. Was that old saying not: There is no space between C and assember for an even unsafer programming language?

    But on one point you are right: *not* in C++. I pitty the guy: He needs to write Ultra-Stable software in a programming language unsuitable for Ultra-Stable software.

    Martin

  321. Re:I don't know why this dominates the first page. by alex_tibbles · · Score: 1

    std::copy vs.

            int n;
            while (cin >> n)
                    v.push_back (n);

    Once you put in some braces to limit the lifetime and scope of n (your temporary), and when you factor in the implicit boolean conversion in the while clause, and the fact the code that calls 'copy' to perform a copying operation, I don't think you have much of a readability case. You have 5 lines (including enclosing braces) where std::copy needs 1.

    On auto_ptr, perhaps you're forgetting that the intended use is to convert dynamic lifetime into scoped lifetime, like the built-ins. Eg. having member auto_ptrs instead of member pointers (and therefore the dtor doesn't have to call delete). Yes, I agree it is stupid to write Java style C++ new-ing every object instance, where a stack instance would work, giving you immediate, simple lifetime control (by tieing it to scope).

  322. MOD parent up by krischik · · Score: 1

    Yes - your are right. "Ultra-Stable" is only possible when the libraries are also "Ultra-Stable". But C/C++ libraries are never Ultra-Stable since they are written in C/C++ and those languages are no good stable code.

    Martin

  323. While I can certainly respect your opinions, by hummassa · · Score: 1
    I will say (again) that I disagree with practically everything you wrote.

    I'm sorry, but I just can't agree. It might appeal to a mathematician who wants to see everything use functional notation and hates every language except lisp, but to a non-abstract-elite-ivory-tower-mathematician this is absurd.

    I am a non-abstract-elite-ivory-tower-mathematician. I am an application programmer. And I guarantee you that I rather encounter a
    for_each(components.begin(), components.end(), _1.disable())
    in some code I need to maintain then to encounter
    for(i = 0; i &lt; components.count(); ++i) components[i].disable()
    the first form permits, for instance, components to be a linked list or even a hash. The second is implementation-dependent and if you change the underlying data structure, you'll have extra work to refactor. And so on...

    > Remember std::auto_ptr is your best friend
    Most of the time, no.


    I disagree wholeheartedly. Anedoctal evidence (no evidence at all): In a 40000+ LOC GIS application I once worked, changing all instances of SomeObject* to auto_ptr<SomeObject> eliminated altogether 35 bugs we had lurking in the BTS for a long, long time, with less than one day of work (strange, delayed, errors were suddently transformed in EARLY null-pointer dereferences -- BAM! bug nailed, let's see the next one) My extensive (15years+) C++ experience (*) gave me the following feeling: pointers and arrays to be used only when strictly needed, auto_ptr and vector are the champions, boost::smart_pointers when auto_ptr does not apply.

    > Question 2: How can I actually implement such a decoupling?
    > I would use a simple, socket-base, take-my-data, gimme-my-results scheme
    And thereby slowing your program to a crawl? There is a reason people use CORBA and the like: those frameworks optimize distributed object calls to avoid network hits, often being able to reduce the overhead to be equivalent to a virtual function call.


    While I agree with the "corba can be more optimized by the vendor" part, I really don't see why a well-thought "let's see what I need processed, organize a queue, and let the queue have it's own thread" would slow things to a crawl... Maybe I have an more "hands-on, not a lot of third-part libraries" approach, so I'll rather give up on that point than debate it further. (ie, I'm conceding that maybe CORBA would be better)

    (*) yes, I use C++ since Stroustrup first edition, when there were no templates, no multiple inheritance, etc.
    --
    It's better to be the foot on the boot than the face on the pavement. ~~ tkx Kadin2048
    1. Re:While I can certainly respect your opinions, by Chemisor · · Score: 3, Interesting
      > I guarantee you that I rather encounter a
      > for_each(components.begin(), components.end(), _1.disable())

      It is never that simple. The fact that you can't do what you've typed is one of the reasons I dislike it so much. What you really need is:

      for_each (components.begin(), components.end(), mem_fun_ref (&CComponent::disable));

      Things suddenly got uglier, didn't they? But wait, what if you need to call a function with an argument? Gotta use a bind2nd adaptor to wrap it, and then it becomes:

      for_each (components.begin(), components.end(), bind2nd (mem_fun_ref (&CComponent::SetParameter), value));

      Wait 'till you try to explain to some maintaining programmer how to untangle that! Oh, and just for laughs, try to debug this thing. Put an assert in SetParameter, and you get a lovely callstack from gdb:

      (gdb) run
      Starting program: /home/user/tmp/tes
      tes: tes.cc:18: void CComponent::SetParameter(int): Assertion `!"Check out the callstack!"' failed.

      Program received signal SIGABRT, Aborted.
      0xffffe410 in __kernel_vsyscall ()
      Current language: auto; currently c
      (gdb) where
      #0 0xffffe410 in __kernel_vsyscall ()
      #1 0xb7d36126 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67
      #2 0xb7d37b40 in *__GI_abort () at ../sysdeps/generic/abort.c:88
      #3 0xb7d2f610 in *__GI___assert_fail (assertion=0x6 <Address 0x6 out of bounds>, file=0x6 <Address 0x6 out of bounds>,
      line=6, function=0x80495a0 "void CComponent::SetParameter(int)") at assert.c:83
      #4 0x080485f6 in CComponent::SetParameter (this=0x804b008, arg=42) at tes.cc:18
      #5 0x08048ac3 in std::mem_fun1_ref_t<void, CComponent, int>::operator() (this=0xbfe2cacc, __r=@0x804b008, __x=42)
      at stl_function.h:826
      #6 0x08048ae8 in std::binder2nd<std::mem_fun1_ref_t<void, CComponent, int> >::operator() (this=0xbfe2cacc, __x=@0x804b008)
      at stl_function.h:446
      #7 0x08048b0c in std::for_each<__gnu_cxx::__normal_iterator<CCompon ent*, std::vector<CComponent, std::allocator<CComponent> > >, std::binder2nd<std::mem_fun1_ref_t<void, CComponent, int> > > (__first={_M_current = 0x804b008}, __last=
      {_M_current = 0x804b00c}, __f=
      {<> = {<No data fields>}, op = {<> = {<No data fields>}, _M_f = {__pfn = 0x80485c4 <CComponent::SetParameter(int)>, __delta = 0}}, value = 42}) at stl_algo.h:158
      #8 0x08048740 in main () at tes.cc:26
      (gdb)

      Now that's something to scare newbie programmers with! Oh, and forget about putting a breakpoint inside the loop; templated functions aren't targetable until executed.

      > in some code I need to maintain then to encounter
      > for(i = 0; i < components.count(); ++i) components[i].disable()

      So why not just use an iterator loop? for_each does not have a monopoly on it:

      foreach (compvec_t::iterator, i, components)
      i->disable();

      (foreach is a macro I wrote because I use this construct so often)

      > first form permits, for instance, components to be a linked list or even a hash.
      > The second is implementation-dependent and if you change the underlying data
      > structure, you'll have extra work to refactor.

      If you use iterator loops, this wouldn't happen to you.

      > I once worked, changing all instances of SomeObject* to auto_ptr
      > eliminated altogether 35 bugs we had lurking in the BTS for a long, long time,
      > with less than one day of work (strange, delayed, errors were suddently
      > transformed in EARLY null-pointer dereferences

      Why were you using SomeObject* in the first place? When I was advocating moderation in the use of auto_ptr, I wa

    2. Re:While I can certainly respect your opinions, by unDees · · Score: 1
      Wait 'till you try to explain to some maintaining programmer how to untangle that!

      Already have done. Both times I've explained quickies like that to maintenance programmers, they understood immediately, and preferred its cleanliness (yes, even with mem_fun_ref and ampersands).

      Oh, and just for laughs, try to debug this thing. Put an assert in SetParameter, and you get a lovely callstack from gdb:

      Looked pretty clear to me. You get the file, line, and function where the assert happened.

      Now that's something to scare newbie programmers with! Oh, and forget about putting a breakpoint inside the loop; templated functions aren't targetable until executed.

      True, but I can count on one hand the number of times I've wished for that. Put a breakpoint inside SetParameter instead.

      So why not just use an iterator loop? for_each does not have a monopoly on it:

      Your foreach macro does indeed look pretty cool.

      And I agree completely, but while you replace pointers with auto_ptr, I prefer to restructure the code to eliminate the need for any explicit memory management altogether.

      Isn't using auto_ptr a way to reduce the need for explicit memory management? It sounds like you guys at least agree on that general goal.

      --
      "I call a baby goat a 'goatse.'" -- my non-Internet-savvy 6-year-old stepdaughter
  324. Re:I don't know why this dominates the first page. by Anonymous Coward · · Score: 0

    my my you do go on. trouble is some of what you say might be right, but then you go and reveal your complete misunderstanding of the basics of QM (as if the notation matters at all!).
    and actually, reveal a misunderstanding of the relationship between physics and mathematics. pretty good going for a post about iterators.

  325. You need a High Integrity Toolchain by krischik · · Score: 1

    Hello,

    I am sorry to tell you: If you need to write ultra-stable software then you need a propper "High Integrity Toolchain". My suggestions:

    http://www.praxis-his.com/

    and

    https://www.adacore.com/gnatpro_high_integrity.php

    There are no two ways around it. Speed is no issue - Ada is just as fast as C++. The libraries are more tricky. But then: have you ask yourself: "Are those libraries ultra-stable?"

    If they are not then your efforts are furtile. And most likely they are not. Most C/C++ library vendors don't have ultra-stable in mind when they create there libraries. That's unlike for example Ada library vendors which allways take stability into account.

    Others said it before, suggestion other languages and I repeat it: C++ is a no go for ultra stable.

    Martin

  326. Reference counting... by hummassa · · Score: 1
    is easy to use with less memory leaks. How? It's enough to transform every "shareable" reference in a doubly-indirect reference (IOW always use references-to-references instead of references-to-stuff). The intermediate nodes get reference-counted, and they can even be destroyed when you destruct the leaves. It's a nice trick:
    $a = { a => 1, b => 2 };
    $b = { c => 3, d => 4 };
    $c = { e => \$a, f => \$b };
    $c{g} = \$c;
    and so on...
    --
    It's better to be the foot on the boot than the face on the pavement. ~~ tkx Kadin2048
  327. It's the coder's fault not the language by FingerSoup · · Score: 1

    Yes, C++ has faults which make it EASIER to cause a crash, but it is the coder who has to ensure that it doesn't. making sure your app has as simple a design as possible, always check for ANY AND ALL invalid data (Create objects with their own validation functions), and ensure both your design and code are well documented. Tricky bits of code, involving memory management, should be avoided as this is the cause for most errors in C++. If possible, limit all memory management code to constructors/destructors and VERY specific resize code. Document inheritances, and avoid tricky multiple inheritance situations. Furthermore, you should ALWAYS have a development cycle that contains a long testing phase, with the ability to test your extremes, as well as testing as close to real world situations as you can - Real users will crash your software much faster than any programmer with knowledge of the internals. Always use strong error handling, and code using try/catch blocks for exception handling - if you're going to have an error, handle it gracefully. Once you have a solid program base from this process, you can start worrying about crash resolution strategies that may increase the complexity of your code - overseer processes and the like. When in doubt, go back to basics and build simpler code. If you don't confuse the coder, it's harder to confuse a computer to cause a crash.

  328. Crash Free by gsgiles · · Score: 1

    It is very straighforward to write a program in windows C++ that is crash free. You wrap the outer main in a structured excpetion handler for all crash events. This will make the program uncrashable it the expense of orphaning, that is leaking, heap memory. This is a bad idea as it will protect bad code from it's own, deserved demise. You want crash proof code? You should spend more time in QA than development and start with a good design. Iterate until the code behaves as desired. This is not a technology issue it is a cultural issue. History is replete with inferior cultures that fail.

  329. Re: Sorry, *not* in C++ and C by HermanAB · · Score: 1

    Yes, you can do dangerous things with C - but that is true of any language. Even Ada has pointers and Goto statements. However, with C and other flat languages, you can prove how much memory the program will use, for example. The biggest problem with C++ is that there is no explicit way to know whether an object can be safely deallocated. So C is deterministic, while C++ is not.

    --
    Oh well, what the hell...
  330. Re:I don't know why this dominates the first page. by csirac · · Score: 1

    It does one thing, then another. No computer has ever worked functionally, and no computer ever will.

    That's a bit short-sighted, speaking as someone converting imperative ISO-C code into FPGA logic.

    I was working with Confluence (write [functional!] Scheme-ish code, out pops massive RTL netlists for your FPGA to re-wire its logic with), but it seems the project has taken a sharp turn towards Ocaml...

    FPGAs are fascinating things... and yes, if you express a function that evaluates (at "compile" time) as recursing 15-deep, it can replicate that function 15 times so that it all happens in one clock cycle (or to save chip space you can rig it up to take 15 cycles on just one instance of the logic, with an accumulator/FIFO idea).

    I wish I could get a permenant job working with them.

    Well, back to hacking x86 assembly on a 15 year old 16-bit MS-DOS app :-(

  331. Re:I don't know why this dominates the first page. by Chemisor · · Score: 1
    > Once you put in some braces to limit the lifetime and scope of n (your temporary),

    Well, if you want to do that, it is easier to use for:
    for (int n; cin >> n; v.push_back(n));
    > You have 5 lines (including enclosing braces) where std::copy needs 1.

    As much as I like one-liners, I would still prefer three short lines to one really really long one.

    > when you factor in the implicit boolean conversion in the while clause

    You might think of it as a return value instead, reading the while as "while you can do cin >> n, push it back".
  332. Code in JAVA using the native interface by kafros · · Score: 1

    From your post i gather the following: 1. Ultra stable application (managed code seems to me the only solution for minimum effort/time) 2. Portable application 3. Need to use existing C++ libraries I recommend doing all coding in JAVA and calling all the existing C++ libraries that you are given using JAVA's native interface (JNI). Lets suppose that you are given a library that does something ultra-super-ific and you cant do without. public static native int callUltraSuper-ificCppMethod(string param1, long param2); then go and write the wrapper code that thanslates parameters/return types from/to JAVA, c++

  333. Patterns for stable design by Anonymous Coward · · Score: 0

    Hi,

    I would recommend you to read Joe Armstrongs PhD thesis (http://www.lib.kth.se/Fulltext/armstrong031205.pd f), which is titled "Making reliable distributed systems in the presence of software errors".

  334. Re:I don't know why this dominates the first page. by Chemisor · · Score: 1

    > For example, in a message-passing multithreaded environment, messages are often
    > created by one object, passes through a message queue, and destroyed when a pool of
    > thread, which often is part of another object, has finished processing it.

    Yes, you might do that, but my pattern would still work better even here. Create a message queue object which will be the owning container. Queue messages with msgq.push_back (new Message). Read messages with msgq.front()->Method(), then pop_front (which will delete it).

    However, I would take it one step further, as I did in the code I'm presently working on: marshal the messages into a bytestream and queue messages as memory blocks. That way you can not only spread the work among threads, but also among different processes or even over many computers over a network. This is basically how CORBA and DCOM work.

  335. Re:I don't know why this dominates the first page. by Chemisor · · Score: 1

    > I was working with Confluence (write [functional!] Scheme-ish code

    That's not the computer. That's your LISP programming language that you use to program the computer. Programming languages can be functional, at the cost of some overhead. Your FPGAs are still algorithmic, they do things sequentially, one thing per clock cycle.

    > if you express a function that evaluates (at "compile" time) as recursing 15-deep,
    > it can replicate that function 15 times so that it all happens in one clock cycle

    Sure, you can write multiprocessing directives with a functional language too. In an algorithmic approach you would iterate over the available processors and spread the work among them, which is what the hardware would actually do.

  336. ACE by avdi · · Score: 1

    You need to look into ACE. ACE is a set of middleware libraries that were designed for precisely the purpose you describe - high-performance, mission-critical systems. Doug Schmidt, the guy behind ACE, has written numerous papers on the usses surrounding such systems, which are also available on that site. He was the first to document a number of important patterns in high-performance netwrked systems, like Reactor, Proactor, and Futures. He's also written books, including books of patterns for distributed reliable systems.

    From that site you can also find TAO, a free CORBA framework based on ACE. TAO is the test bed and driving force behind the CORBA realtime spec, which is a version of CORBA for realtime systems which demand high and deterministic performance. I believe TAO includes services supporting failover and other reliablity strategies.

    ACE and TAO aren't just research software. They are used in mission-critical systems by major defense and aerospace contractors. I work at one such.

    Sorry to sound ilke a shill. I'm not paid by them or anything; I'm just a programmer who uses ACE for his job and has been favorably impressed with it.

    --

    --
    CPAN rules. - Guido van Rossum
  337. 2 stage construction by SkunkPussy · · Score: 1

    If robustness is an issue, then you need to look into two stage construction or a similar method. This is required for two reasons - firstly C++ class construction simply does not support the situation where either malloc operations fail or exceptions are thrown in the constructor (as the class has not been constructed, there is no destructor created, thus all malloc'd memory is instantly leaked).

    Two stage construction places all code that requires memory allocation into a 2nd stage constructor function so that no memory is lost if the constructor fails.

    (In addition two stage construction allows constructors to be inherited which provides an advantage in some situations).

    There is plenty of information on google concerning this technique.

    --
    SURELY NOT!!!!!
  338. We are only Humans. by krischik · · Score: 1

    Hello,

    but we are all only Humans and we err from time to time. And if I use a programming language that finds 10 times as many of my mistakes (i.E. by automaticly "check for ANY AND ALL invalid data") then C that this is a huge difference. Ada would be such a language

    But the OP speaks "Ultra-Stable". If he truly mean what he says then he needs to get the big guns out which find 100 times an more of the all so human mistakes then C. Static analysis tools like SPARK would be such a tool.

    See my other post: http://ask.slashdot.org/comments.pl?sid=176280&thr eshold=1&commentsort=1&mode=thread&cid=14649951 and follow the links.

    Of course there are static analysis tools for C. While they are better then nothing they are very tedious use because C/C++ have so litte to offer security wise.

    Blaming the coder only shows that you do not know what it entails to write true high integrity software.

    Martin

  339. What do you mean? by hacksoncode · · Score: 1
    While there's more to this, what strategies should a developer take to insure that the resulting program is as crash-free as possible?

    I think your first and biggest problem is that your haven't defined what you mean by "as crash free as possible". What kind of uptime requirements do you have, what kind of data loss and retention requirements? What's the cost of a failure? What's the cost of preventing a failure? What are the security requirements? Does the system have to resist malicious external interference (and if so, that's a whole new can of worms^H^H^H^H^Hquestions)?

    If you don't answer these kinds of questions first, no advise that anyone can give you be anything more than a guess.

    That said, probably the biggest 2 suggestions I would have are: 1) Don't overengineer. Make your solution as simple as possible, but no simpler. 2) Code review every damn line of code written or changed on the project with at least 4 people in the room.

  340. Re: Sorry, *not* in C++ and C by krischik · · Score: 1

    The problem with C/C++ is not that you can do dangerous thing. Ada's has very interesting low level contructs. The problem is that it is the normal way to do things. Example:

    signed int x = -1; // 200 lines later...
    unsigned int y = x;

    Remember: Programms are often done by teams and monitors usualy hold less then 200 lines. And it is such a simple thing for a compiler to just tell me that the value just does not fit.

    Martin

  341. dynamic_cast by krischik · · Score: 1

    If only dynmaic cast could be used for:

    sigend int x = -1; // 200 lines of code

    unsigned int y = dynamic_cast (x);

    But you can't. Some idiot decided that dynamic_cast is for class pointers only. But in real live you are far more likely to cast signed unsigned or short long.

    And boost has no:

    typedef range day_of_month;

    either. It's possible - I wrote such a template myself. But is't not part of the all mighty boost.

    Allways arrays and pointer - but you know: that JPEC virus uses an interger overrun to worm itself into your computer. Windows, Linux, MacOS - they all hat to replace there jpec library because integer ranges are not checked in C or C++.

    Martin

  342. Re: Sorry, *not* in C++ and C by HermanAB · · Score: 1

    I prefer strongly typed languages. Prof Wirth did a few things right with Pascal, notably strong types and strings with a length value. Gawd knows how many problems are caused by C null terminated strings exceeding the boundaries.

    --
    Oh well, what the hell...
  343. Re:I don't know why this dominates the first page. by csirac · · Score: 1

    That's not the computer. That's your LISP programming language that you use to program the computer.

    Ah, no my friend - firstly there is no computer involved at all, just an FPGA chip. I could wire up the contents of the FPGA chip to mimic a CPU and a full System on a Chip, complete with ethernet and audio and VGA sub-systems if I like..

    Confluence was but one HDL (Hardware Description Language) I experimented with to write EPXRESSIVE code. There was only sequentiality because I wired the clocks up that way.

    It's truly WYSIWYG: "That's your LISP programming language", yes it is - it also translates directly, every statement, into dedicated hardware. There is no assembly language, no smaller instructions it gets broken down into, no OP codes, no nothing - it just gets hard-wired into dedicated logic that way.

    Your FPGAs are still algorithmic, they do things sequentially, one thing per clock cycle.

    FPGAs are a bit of a specialty field, but you do not understand them.

    There is no "central" anything on an FPGA. None at all. They certainly don't do just one thing per clock cycle: for starters, they can have thousands of clock circuits all running at once. Secondly, if it's only doing one thing per clock cycle, then that's only because you've wired it up that way - and you're probably not using the FPGA efficiently.

    The key to getting the maximum work out of an FPGA is parallelism... creating logic that will process as much as possible per clock cycle, but with keeping the complexity down so that the clock speed itself doesn't slow down so much so as to work against you...

    You are saying nothing "ever" happens all at once when talking about throwing sets of numbers at something: but I say, with FPGA and HDLs like Confluence, you can actually write functional code that translates - line by line - into physical hardware that will evaluate everything in parallel, all at once.

    Handel-C, for instance (although not functional) will translate every line of code into physical hardware. Doing i++;? It will create adder logic, wire up registers for input from the previous statement and output onto the next (it's a bad example that implies FPGAs have a concept of "execution" like a CPU that you're clinging to, I just wanted to talk about the dedicated-hardware-for-every-statement thing).

    On an FPGA, it's all happening at once. There is no such thing as a CPU unless you create one. There are no bottle-necks unless you create one.

    That's why when one of my projects in image processing, my FPGA whose master clock ran at 65MHz (other speeds were derived from this clock to drive complex logic down to speeds of about 4MHz) out-performed a 3.0GHz Pentium 4 by a factor of 10. Because where as the P4 was too general, my FPGA design could do in just one clock cycle something that took the P4 1000s of cycles because my FPGA logic was dedicated to the task.

    DSP and Control Systems theory also requires a good understanding of higher mathematics, although now we're entering the realm of EE which is my background... functional programming certainly is extremely useful in FPGA design if you have a problem that can be expressed functionally, which is often the case in electronics.

    And think about it: designing FPGA logic is much like building larger "macro" circuits with off-the-shelf chips. Each small part serves a specific "black-box" function. Unlike specs in software, specs in electronic engineering often are mathematical, where signals require some sort of transformation - somtimes in the time domain, sometimes in frequency domain, sometimes complex-S...

    I'm not disagreeing with your overall argument, just saying that you need to open your mind a bit - "never" is a very strong word :-)

  344. There is no silver bullet. by natoochtoniket · · Score: 1
    The key elements are:
    1. Highly expert people;
    2. Careful process;
    3. Plenty of time to get it right.

    The process should not be new. Use well-understood engineering principles and processes. (Specify/Design/Code/Verify, and iterate as needed) New processes invite shortcuts and misunderstanding.

    For the verification and testing, also use well-understood engineering principles and processes. (Specifiy/Design/Code/Verify the tests!) The tests should be automated, so you can eaily repeat them.

    Verify every verifiable thing, and design them to be verified. Test every testable thing, and design them for testability. Review, Verify, Review, Verify, absolutlely everything. Plan a huge fraction of your total budget for review and verification.

    If you design in try..catch logic, or N-version programming, voting algorithms, or similar stuff, make sure you apply sound process and verification to each of the alternative codes... If you don't, it is very likely they will all be wrong. Be aware that added complexity only increases opportunities for errors. One correct algorithm is better than several incorrect algorithms.

    Measure reliability, using test-case failure rates and frequencies, and review/verification findings, to know when you reach the required reliability.

    Do not schedule any deliveries until the reliability measurement tells you it is almost ready to deliver. There is an old saying that goes something like "Feature, Schedule, Quality. Pick any two. You can't have all three." If you want very high quality, you cannot stick to a schedule.

    There really are no shortcuts.

  345. Doomed by TaleSpinner · · Score: 1
    This is just my opinion, but I think you're screwed. I came to the conclusion years ago that no one can write stable software in C++, no matter what they spend on the task or who they get. I don't recall who first said it, but I wholeheartedly agree with the sentiment: "I wouldn't allow anyone to program in it but me."

    The reasons for this are as large and as complex as the language itself. However, just to touch on a couple of the most obvious: incompatibility between compilers (and even within a compiler as new features are added), to some really poor encapsulation techniques (some of this can be addressed using opaque data types and discipline, provided your management is prepared for complaints from coworkers about how hard it is to understand your code). And then...well, you get the picture. I wouldn't wish a C++ project on my worst enemy (and I could have, and I didn't).

    If your management is insisting on C++ then they are already emboiled in micromanaging details they should not be - start polishing your resume, you are going to need it soon, no matter how the project goes.

  346. bullshit by idlake · · Score: 1

    There's no excuse for buffer overflows and memory leaks in C++, not with TR1's smart pointers and not with the standard library's containers.

    I've been using smart pointers for nearly as long as I have been using C++, and I can assure you: they don't guarantee correct memory management. There simply is no way to do predictable, safe, well-defined memory management in C++. All smart pointers can do is reduce the probability that you screw up, but at a steep cost in terms of performance, and without any guarantee that third party code is as careful as you.

    That's not even considering garbage collectors which have been available in C++ for years.

    The only garbage collectors that work with normal C++ implementations are conservative, and those are both inefficient and not accurate.

    You can't fix C++ without massive backwards incompatibilities.

  347. Don't use non-deterministic features by richardlvance · · Score: 1

    Just use the C stuff within C++. Spawning stuff in run time (with hope it actually gets killed when you destruct) is dangerous to stability. Don't use virtual file systems (operating system). Go back to good old days of static coding. Load once and everything you need is in memory, data is initialized at load time as well as at first useage. Kepp it simple and it should be predictable, (stable).

    --
    cursethedarkness
  348. Re:I don't know why this dominates the first page. by unDees · · Score: 1

    One thing at a time? Do you even know how FPGAs work?

    --
    "I call a baby goat a 'goatse.'" -- my non-Internet-savvy 6-year-old stepdaughter
  349. Re:I don't know why this dominates the first page. by Anonymous Coward · · Score: 0
    The entire hodge-podge nonsense we call quantum mechanics stems from the attempt to describe a complicated system as a function. Instead of trying to get a set of time-value maps for the whole system, it would be more appropriate to look at the system's constituent parts and algorithmically simulate them through time. That way you wouldn't get any "spooky action at a distance", stuff being there and not there at the same time, and all other equally ridiculous denials of reality.


    You have no idea what your talking about in this case.
    First of all if you think that quantum mechanics is "hodge-podge nonsense" then what are your theories on how the laser in your computer works?
    Secondly "stuff being there and not there at the same time" has been SEEN (i.e. with the eyes) in the lab(Bose-Einstein). When you want to rant in the future, talk about stuff you have studied inorder to not make your self look like a moron.
  350. Language stability by steveski74 · · Score: 1

    I'm a little stunned at the fact that you think C++ is inherently less stable and crashable than other languages. True in C++ there's generally more you need to do than in other languages, but frankly, my first C# application (with garbage collection, etc) had a major memory leak. I only picked it up because I happened to be looking at the task manager and noticed the memory usage going up, not because things were unstable. I was calling .Dispose on an object and just assigning null didn't help for some reason. I also get errors popping up all the time and need to wrap code in try catch blocks. C++ also has this construct so my advice to you is make as many mistakes as possible and get used to spotting where code is likely to be vulnerable and take action to avoid crashing. Employing patterns and decoupling can prevent individual modules from stopping entirely, but it's not going to stop the individual modules from being unstable. You still need to do explicit error checking whenever you write code, regardless of the language or patterns you decide to use. If you want to write platform independent code the use an API which has the same goal. For GUI apps use Qt or GTK, and for 3d games use Ogre3d. But using these won't eliminate the need to follow sound error handling practices. A programming language will always give YOU the option of how things should be handled in the event of an exception.

  351. Design, develop test and then develop some more by ACORN_USER · · Score: 1
    I think that there is no reason why writing the application in C++ should imply that it will be unstable. I like the idea of decoupling your processes and personally write off the 'managed code' concept unless you're building for .net land. Make sure that the separation between your components makes sense, and as someone else has said, unless you need to, there's nothing to imply that your whole system should be in C++. As long as your centralise your core functionality and dependencies on flaky libraries in one place. I built an application a couple of years ago which exposed some C++ functionality over soap, using gsoap. This interacted with perl and java soap clients. I've also in the past written applications which monitor the state of applications deemed to be unstable and recover them in failure. Obviously, this should be something which runs whilst you're resolving your bugs and if you test and develop towards a clean release, you should never need it in production.

    That's my 0.2 EU's.

  352. Re: Sorry, *not* in C++ and C by OneSmartFellow · · Score: 1
    The biggest problem with C++ is that there is no explicit way to know whether an object can be safely deallocated

    And how is this different to C ?

    void(char* p)
    {
    free(p);
    }
    char* ptr = malloc(1024);
    func(p);
    free(ptr);
    Of course this is contrived, but since you don't necessarily know what 'func' is going to do, how do you know it's safe to free the memory ?
  353. Re: Sorry, *not* in C++ and C by HermanAB · · Score: 1

    C++ can trigger an exception in the middle of a constructor for example. So when you then get to the exception, it is not clear what to do.

    --
    Oh well, what the hell...
  354. How I do it... by Anonymous Coward · · Score: 1, Interesting
    I write this kind of software for a living, although perhaps less complex than yours, since the critical part of mine doesn't have a GUI. On the other hand, I have to survive power-cycline with no problems. But basically there are two parts:
    1. Pepper your code with assert() calls to make sure that if anything goes wrong, it crashes quickly.
    2. Make sure that it can restart seamlessly.
    What's important is that the crash/resume cycle is faster than the necessary response time. If you have hard real-time constraints, life gets a whole lot nastier, but if an occasional half-second glitch is okay, things can go well.

    You have to think really hard about state, and do everything as a two-phase commit. Network connections to applications that don't resume cleanly are particularly tricky; you have to save and restore the sequence numbers across the crash/reboot. This requires NOT using the OS TCP implementation, or hacking it heavily to not send the ack until you've committed the state produced by the packet recpetion.

    I have crashing bugs happily running in production, becuase it gets back up and keeps going with no problems. The bad problems are reboot loops, when the "resume from crash" code crashes. You have to be very paranoid there.

    But it really does work remarkably well. Oh, one more tip: add a version number to your state files. Any time you don't change it, you can perform a software upgrade in-place by crashing the old version and letting the new one resume. Otherwise, you have to have scheduled downtime for every upgrade.

  355. Haskell [Re:You're not the first one....] by j.leidner · · Score: 1

    I know the Haskel 98 report, but by standard I meant a normative document, preferredly issued by an international or national body like ISO (or ANSI, ECMA), which is usually necessary step to give the language credibility (not by virtue of its design, as Haskell is rather elegant, but rather by showing that there is enough interest from industry backing it).

  356. Project COSA? by Anonymous Coward · · Score: 0

    How come now one has mentioned Project COSA when it comes to writing, as you termed it, 'bulletproof code', a 'silverbullet'.

    The founder of Project COSA intends to create just that, code that is guaranteed to be bug free. http://www.rebelscience.org/Cosas/COSA.htm

  357. The best way to build a bullet-proof app by c0d3h4x0r · · Score: 1

    Well, in C++ at least, the best way is to employ a few simple techniques with extreme dilligence:

    1. With each line of code, handle all possible failure cases, however unexpected or unlikely, gracefully in retail builds.

    2. Do not use Asserts or empty catch blocks as your only form of "error handling".

    3. Standardize on using either "function return values" or "exceptions" as your form of error passing up the stack in your codebase, and stick to it.

    4. Never ignore exceptions or function return values unless it's intentional and for good reason. To indicate that choice, cast the function call explicitly to (void) to make it clear that ignoring the result is intentional, and add a comment documenting the reasoning.

    You should never just have an Assert, ever, anywhere, because it will do exactly zilch in retail builds. You should *always* use asserts in combination with code that takes appropriate action in the event the assert happens to be violated for whatever reason. I'm actually much more of a fan of utilizing a carefully-crafted "Ensure" macro, which always evaluates the condition in retail builds, asserts if the condition evaluates to false, and then has either a "goto" label to jump to the relevant point (such as function clean-up and exit) or a function call pointer (which is the handler to execute upon failure).

    Similarly, you should not just eat exceptions in most cases. Only do so when you're clearly being intentional about it, and add a comment to point out that the empty catch handler is intentional and explain why.

    Standardizing the way you let functions pass errors back to their callers (either by function result, or by exception throwing) is important because when you get a mix of approaches you have to perform acrobatic coding to properly handle failure cases. Stick with one or the other. Obviously anything can throw an exception at any time, so you should always trap exceptions... but ideally each function traps its own exceptions and then returns an appropriate result code to its caller, or else all the functions in your app are "void" return type and throw exceptions containing error codes to communicate failure back to the caller.

    --
    Moderator hint: a comment is neither "Flamebait" nor "Troll" if it is true.
  358. Design patterns to the rescue by Tattva · · Score: 1

    There are some simple design patterns that can really help you. The Null Object and the RAII (Resource Acquisition Is Initialization) patterns are essential to stable C++ code. The STL or an equivalent library is the last piece to the puzzle.

    The Null Object pattern removes the defect-prone NULL value checks throughout your code by creating an object that represents null behavior for any situation where the existence of a real object is illogical.

    The RAII pattern prevents resource leaks by tying resources to object lifetimes. By using stack allocation through the STL container and smart pointer (if needed) classes you can pretty much never use the "new" keyword in your application. You will have to create a copy constructor and an "operator =" deep copy method for STL to be able to handle your classes as value classes, otherwise you will need to use smart pointers.

    I've heard people criticize STL and especially its smart pointer feature, but after extensive use I have no complaints other than the god-awful error messages compilers give you when things don't go right and the poor debugging support for visualizing such containers.

    --
    personal attacks hurt, especially when deserved