![]() |
|
Which language is best? |
Goalie Ca
Member #2,579
July 2002
![]() |
A while back i discovered the boost programming libraries for C++. While i wish the language had more features built in (kudos to C# for having an awesome language but horrible windows libraries). I've been using boost smart pointers, ublas, etc. In fact some of the boost code will end up in the next standard for c++. Smart pointers though are basically good reference counters but there are several kinds for each purpose and add very little overhead. Of course the nice thing about boost is that it is very well written and adds very little overhead. http://www.boost.org/libs/smart_ptr/smart_ptr.htm ------------- |
Matthew Leverton
Supreme Loser
January 1999
![]() |
I think the people who are saying that memory management isn't a big problem are either a few of the world's best programmers or have never worked for multiple years on a large project with a group of other programmers with varying levels of talent. Almost every single remote security vulnerability is due to bad memory management with programs written in C. These aren't just isolated cases of a few bad programmers. Memory management sucks and if you are bitten by it, you might just be spending a few days trying to trace it down. Especially if you have to work through someone else's messy code... In a corporate world, that translates to lots of lost money. After enough of those problems, it becomes cheaper to buy better hardware to run the (slower) higher level languages. The longer I program, the more I appreciate high level languages. It's not that I don't understand how to access memory, it's just that it's a waste of my time. About the only place I think C or C++ belongs is in DLLs that provide speed critical methods for a higher level language to access. Also, there are some applications (like most Allegro games) that don't require a lot of complex memory access that are still a good fit for C/C++. |
23yrold3yrold
Member #1,134
March 2001
![]() |
I can appreciate that, and maybe my mind will change if I ever work for a big company on this stuff. For the most part though, on projects like most of us do, a little preplanning and your program should manage the memory just fine. -- |
Goalie Ca
Member #2,579
July 2002
![]() |
Quote: or have never worked for multiple years on a large project with a group of other programmers with varying levels of talen Well I must add that there are tons of different types of programming. I didn't want to say this but "the right tool for the job" needs to be mentioned. For the work i do, managed code simply won't cut it and isn't even necessary. That said i would love to see more managed interfaces to game libraries. Managed Directx looks nice and so does Tao. I'm sure the allegro .net interfaces are nice indeed. Personally i wouldn't be surprised if in 10-15 years we don't see managed code as part of the big titles just because development time is short and games are becoming far more complex. The runtimes are becoming very efficient as well. Plus, since we're all talking about making parallel code for multi-cores and the rest it would be nice to make use of built-in language features rather than calling sem_lock and the rest. It would be neat to see runtimes take a look at the hardware its running on, ie: number of cpu's, ram, etc. and compile it just for that system. ------------- |
Matthew Leverton
Supreme Loser
January 1999
![]() |
Quote: I didn't want to say this but "the right tool for the job" needs to be mentioned. That's what I mean when I say that there are programs "that don't require a lot of complex memory access that are still a good fit for C/C++." Usually where memory access comes to bite you is when you are dealing with arbitrary input from (untrusted) users. If you're not working in that realm, then a lot of your memory bugs may simply go safely unnoticed. Working with C makes me feel like I know what I'm doing and what's going on, but I don't get a "rush" from that anymore. Assuming that the program runs "fast enough," I'd rather just get the job over as quickly as possible. |
Goalie Ca
Member #2,579
July 2002
![]() |
Heh i totally agree i don't get a rush from coding at all, i get my fix solving problems and making it work. Worrying about things other than the problem at hand really sucks. Another really nice thing about bytecode and the rest is the virtualization that comes from it. For anyone who's dealt with large systems, servers, multi-users, etc. virtualization is a godsend. Xen is actually a really cool way to run servers. ------------- |
Karadoc ~~
Member #2,749
September 2002
![]() |
Evert said: I'm not sure I agree: in a complex programme, you can have correlations between lines that lead to memory leaks even if each line by itself looks fine. Therefor, I would expect the chance to scale quadratically with the number of lines of sourcecode. Yeah, in the back of my mind while I was writing the 'linear' thing I was wondering about memory errors caused by combinations of lines rather than just one erroneous line. But I kind of swept the idea under the carpet by imagining that we are programming in a nice and modular fashion. I reckon that whenever there is a memory leak, it is due to just one erroneous section of code. Either bad programming in one of our modules, or bad use of a module. I guess there could be examples in which it isn't really like this, but I think they will be rare. I truly believe that the probability of an error would scale approximately linearly**. However, when you do have a memory error, the difficulty of finding and correcting it probably increases exponentially. Fortunately, those of us who are scared of memory errors can use memory management stuff in C++ (and not have to resort to an awful language like Java (** something just occurred to me while I was writing that. If the probability of having a memory error scales linearly, that means there will be a program size for which you are certain to have an error... That doesn't sound right.) ----------- |
Goalie Ca
Member #2,579
July 2002
![]() |
I'd guess that the probability of a memory leak or other memory errors would increase wrt how the object/pointers are being passed around. The nice thing about smart pointers is that when the pointer goes out of scope or does anything else then the count changes. Garbage collection effectively does the same thing but then again only full blown gc's like java's can deal with cases like circular references. As for buffer overflows you can easily avoid things like that by using classes to manage and perform the checks automatically. This includes string classes, array classes, etc. C++ can throw/catch exceptions but i hardly see anyone use them! The problem with C++ is that none of these features are standard anywhere. Someone has to take the time and develop a 3rd party library and people actually have to adopt it. It is a pain in the ass when every library has its own way of dealing with this and none of it interoperates. Even so, "best coding practices" are needed. You still have to take more care than you do with java for instance. But on the flip side if you are writting a large application you need to know exactly how the gc behaves to ensure things go smoothly. GC does not come free by any means. ------------- |
Jonatan Hedborg
Member #4,886
July 2004
![]() |
It is of course not impossible to write perfect, memory-error free code. The problem is that you have to! There is a lot of effort put into making those destructors, deletes, making sure there are no dangling pointers and what-not. With a GC'ed language like java, you dont have to think about it.
|
nonnus29
Member #2,606
August 2002
![]() |
Quote: It's not that I don't understand how to access memory, it's just that it's a waste of my time.
That's the point exactly. |
ImLeftFooted
Member #3,935
October 2003
![]() |
Quote: There is a lot of effort put into making those destructors, deletes, making sure there are no dangling pointers and what-not. For you, yes. Different people have different tastes in languages. To me there isnt much effort for doing dtors, deletes and making sure there are no dangling pointers. Its about a 2-5 second decision for me while I'm designing a given compilation unit. Some people think of classes / OOP as a lot of effort with no real benefit. To each his own. |
Jonatan Hedborg
Member #4,886
July 2004
![]() |
Quote: Some people think of classes / OOP as a lot of effort with no real benefit. To each his own. What does that have to do with anything? What i'm saying is that regardless of how much/little time you spend doing your dtors etc, you still spend that time doing that - time you could spend on something else.
|
Arthur Kalliokoski
Second in Command
February 2005
![]() |
Quote: Usually where memory access comes to bite you is when you are dealing with arbitrary input from (untrusted) users. Hmmm.... lemme think <thumps head> Linux kernel is C and asm. Windows is thought to be largely C++. Which one has the buffer overruns again? They all watch too much MSNBC... they get ideas. |
Matthew Leverton
Supreme Loser
January 1999
![]() |
You are comparing a kernel to the entire Windows platform? |
ImLeftFooted
Member #3,935
October 2003
![]() |
Quote: What does that have to do with anything? What i'm saying is that regardless of how much/little time you spend doing your dtors etc, you still spend that time doing that - time you could spend on something else. Maybe it would be worth it for you to program in ASM? less time spent writting useless semicolons and paraenthesis. What i'm saying is that regardless of how much/little time you spend doing your semi colons, parenthesis, etc, you still spend that time doing that - time you could spend on something else. |
Kitty Cat
Member #2,815
October 2002
![]() |
It doesn't matter how "efficient" a language is if the person using it isn't good with it. The efficiency will be lost. Besides, constructors and things actually do something, so it's not like you're wasting time. -- |
Shawn Hargreaves
The Progenitor
April 2000
![]() |
Quote: You are comparing a kernel to the entire Windows platform? Very true. The Windows kernel is almost entirely asm, too. C++ isn't even officially supported for anything that runs in kernel space! (eg. device drivers), although a lot of third party drivers do actually get written in C++. And, the Windows kernel isn't where the buffer overruns happen. Applications are a whole different kettle of fish. On the issue of manual memory management, the real problem comes when you try to reuse code. For a small one person project it is totally possible to do manual memory management and get it 100% correct, but that just doesn't scale. As soon as you have more than one developer working on a codebase, or you want to package up some function as a reusable library, you run into a whole bunch of problems:
These sort of questions are trivial to answer in any given case, but they pile up exponentially as the project complexity increases. I can expose an API and tell my coworker how to use it, that's no problem. But then my coworker wants to use my type as a return value from some other API that he is exposing for someone else, and they're using this alongside a component written by a different group, which had a load of legacy code that doesn't fit out latest conventions, and they're also using a couple of third party libraries that they don't control at all. All of a sudden there can be literally hundreds of different memory ownership patterns in use at the same time in the same program, perhaps straddling DLL boundaries to make things even more awkward, and nobody can fit all this in their head at once to make sure it is all correct. I've only ever seen three techniques that can actually make large scale C++ memory management work correctly:
The thing about reference counted smart pointers is, really this is just a bad form of garbage collection! In a true GC environment, things work just the same as if you had reference counts, but it runs faster because the GC can be optimised to only do periodic sweeps, use generations, work in a background thread, and only kick in after there has been a lot of allocation activity, where reference counts need to be updated every time you transfer ownership of an object (ie. all the time while code is running). So I think GC is a very very good thing indeed. It works better, and is faster, than any of the other options. Quote: Yeah, in the back of my mind while I was writing the 'linear' thing I was wondering about memory errors caused by combinations of lines rather than just one erroneous line. But I kind of swept the idea under the carpet by imagining that we are programming in a nice and modular fashion. I reckon that whenever there is a memory leak, it is due to just one erroneous section of code I think it's the exact opposite: almost all errors happen in the gaps between modules. // EngineInfrastructure.dll Wibble *CreateWhatsit(Flibble *params) { return new Wibble(params); } // MyGame.exe void FlobTheWhatsit(Flibble *params) { Wibble *wibble = CreateWhatsit(params); wibble->Flob(); delete wibble; } Do you see the memory leak? No? There might not be one. A lot depends on the guy who wrote the Wibble type, which is coming from some third source. So in reviewing this code to make sure it is all ok, I (who am just writing the MyGame.exe: I got the Wibble class and EngineInfrastructure.dll from a coworker), have to go and look at the implementation of Wibble to check if it does actually have a destructor, or if there's some other Cleanup() method I might be supposed to call instead. This slows me down, wastes time, and might introduce a bug if I forget to check. Ok, so let's suppose we have coding guidelines that say all types must have destructors. What if Wibble came from a third party that didn't follow our guidelines? I might not know that and would just assume it was ok. There's a bug right there. Or lets suppose Wibble is actually fine. There still could be a memory leak depending on how EngineInfrastructure.dll and MyGame.exe are compiled. Lets say we always build EngineInfrastructure.dll in release mode, to make it nice and fast, but I'm doing a debug build of MyGame.exe. That's probably going to leak because the memory is getting allocated by one version of the runtime libraries, then freed by a different version from a different DLL. But you can't spot that from a code review: you have to know a lot about the compiler and look in the build scripts to even spot the problem. Which is why garbage collection is a Good Thing. I never ever want to write anything with manual memory management ever again. I have better and more interesting problems to spend my time on! |
axilmar
Member #1,204
April 2001
|
Matthew Leverton said: I think the people who are saying that ... Well said. As a programmer many times bitten by C++, I fully agree. Shawn Hargreaves said: On the issue of manual memory management, the real problem comes ... Wise words. Both your comments fit right with my personal experience. I guess the problems are not a coincidence. I had an exchange of rough words over artima.com over this. I am a full supporter of C++ getting optional garbage collection in the standard, but some people think it is not needed. It's truly amazing, in a negative way, that people support the view that C++ does not need garbage collection...including the C++ standards committee and Bjarne Stroustrup himself. When these people realize their mistake, it would be too late for C++. |
ImLeftFooted
Member #3,935
October 2003
![]() |
Shawn Hargreaves said: Which is why garbage collection is a Good Thing. Wow that makes a crap load of sense. I think you've convinced me to like GC. axilmar said: It's truly amazing, in a negative way, that people support the view that C++ does not need garbage collection...including the C++ standards committee and Bjarne Stroustrup himself. When these people realize their mistake, it would be too late for C++. Maybe the solution is to implement your own GC in C++. C++ lets you override the new operator and such, which is probably why Stroustrup doesnt want C++ to force a GC, he just wants to leave the option. |
Marcello
Member #1,860
January 2002
![]() |
D? Marcello |
Goalie Ca
Member #2,579
July 2002
![]() |
I remember reading about C++0x (the next official version) a while back and i dug it up again thanks to google. It's an interesting read but i feel it covers some areas well but falls short in many others. Read about it and you'll see what i mean. edit: edit2: ------------- |
Marcello
Member #1,860
January 2002
![]() |
wow that looks horrific. why not lead dead horses die? |
Evert
Member #794
November 2000
![]() |
Let me begin by clarifying something from my last post: I disagree that using dynamic memory in C or C++ automatically means your program starts getting memory errors or starts crashing. It goes without saying that not having memory to manage means less work. Wether or not a garbage collector is a good thing or not will depend on what your programme is used for. If I'm writing a game or GUI application, I probably don't care either way (I do those by myself anyway). If I'm writing something to do numerical work, I sure as hell don't want a garbage collector running in the background. That's not to say that I wouldn't be allocating and deallocating large chunks of memory in the time critical part of the code anyway. Quote: why not lead dead horses die? Why do people invest time in making FORTRAN 2003? |
Trezker
Member #1,739
December 2001
![]() |
Memory management is were the fun stuff happens. It's the magical place where wonderous bugs appear at random at the worst possible time. DICE told us a story about saving money. One of their programmers thought that they were spending an awful lot of time testrunning the program to see if the latest compile was still running as it should. All those computers are currently working day and night automatically running the latest builds and reporting when shit hits the fan. |
Carrus85
Member #2,633
August 2002
![]() |
Personally, I think garbage collection shouldn't be integrated as a language feature in C++ (ala java where all objects are put onto the heap automatically and garbage collected whenever the gc feels like it), it should be more along the lines of a standard library module. (ala auto_ptr<type>, only something like gc_ptr<type>). The main problem with global garbage collection is that with RAII, you want the destructors to be executed when the object is no longer of use (otherwise mutexes, files, network connections, etc. won't be properly released); unfortunately, there is really no way to call the destructor independantly from the memory allocation/deallocation code (short of overloading the delete operator for an object and using some pooled memory allocation scheme). They could hack the destructor mechanism to do nothing more than execute the destructor code and put the memory into a list to be released later, but then you are shooting the people who want the memory free NOW in the foot. Of course, you can do this exact thing on a case by case basis by overloading the delete operator, but then we are getting back into the realm of "standard library module" again. I agree, a standardized garbage collection scheme would be nice. However, they shouldn't force it on those who desire not to use the GC.
|
|
|