Organizing and managing code?

Started by
16 comments, last by snowmanZOMG 12 years, 1 month ago
I'm not sure what IDE you're using, I'm going to assume MS Visual Studio since it's arguably the most commonly used.


Debugging:

If your applications are closing on errors, you're probably running under release or have debugging disabled for some reason. When an error occurs under debug in MSVC, it will set a breakpoint at the line that crashes. This may be in your code or (commonly) inside a function whose source you may not have access to. Simply find your stack and follow it up until you find familiar code, step through and make sure you don't have any bad values. There are a lot of different techniques for debugging, you really need to find a good book on it.


Memory Management:

I am actually not a fan of "smart pointers", I feel like too much reliance on them signifies a weak architecture. However, they are still a common and useful utility. It's a good idea to get familiar with them. You should also look into memory pools and resource management. There are a lot of ways to manage memory, the most correct method depends on your needs for that specific project. You absolutely do need to use some sort of memory profiling. There are many free solutions. At the very least, you should check out this MSDN topic for simple leak detection.
Advertisement
:((( I write some code and then immediately step through it line by line with the debugger to make sure that it's working as I expected. Occasionally, I find errors or mistakes I wasn't expecting.

I'm pretty good with the debugger, but not good enough to read x86 assembly. Here are some tips for you:
-Keep your code clean, simple and readable. Whitespace is good for preventing eye strain and information overload.

-Every time you use a 'new' keyword to allocate memory, automatically create a 'delete' keyword to deallocate it and make sure that the delete is reached.

-Be consistent with your naming conventions.

-Comment your code. It's for you. When your eyes are bleary, your brain is mush, or six months from now when you have to relearn your code, you'll be happier to read comments than code to figure out what you were thinking.

-floating point precision errors are a bitch to find and debug. If you're comparing floats for equivalence without a tolerance threshold, you're doing it wrong.

-If you're creating a mathematically oriented function and you know the range of valid inputs, throw it into a for loop and iterate through each valid value. Did you get divide by zero errors? did you handle negative values properly? if you're using floats, was your step size small enough to test for floating point precision errors?

-Sometimes it helps to create classes in a seperate project so that you can test and develop them in isolation. Once you know that your class and its member functions are rock solid, you can copy them into your main project and have a higher degree of confidence that they'll work without problems. This also helps to keep your classes loosely coupled.

-Aside from the debugger, my second most useful tool for debugging is pen and paper. Draw out the conceptual idea you're trying to implement and then synchronize the steps with the debugger (example: inserting nodes into a linked list at the front, tail and middle).

-The best bugs are the ones you don't have. A little bit of planning before code writing will go a LONG ways. There are three types of errors: Syntax errors, program errors, and design errors. Syntax errors prevent you from compiling. Program errors are stuff like referencing a null pointer or dividing by zero. Design errors are when you code a program with a broken design and you don't realize it until hours/days/weeks/months later. Planning and diagraming helps avoid them and helps keep your code organized.

-Lastly, stay disciplined. It's easy to get lazy and code something up really quick, but I've found that taking a little bit of extra effort to do things right the first time saves more time and effort since I don't have to refactor what I did out of laziness.

Good luck!

-Every time you use a 'new' keyword to allocate memory, automatically create a 'delete' keyword to deallocate it and make sure that the delete is reached.

Don't use new unless you need a custom data structure or for unique_ptr. Use std::make_shared and std::vector instead (you could also create std::make_unique, I'm sure it'll make it into the standard soon).

A *a = new A;
//use a
delete a;

is very like not exception safe. Better:

std::unique_ptr< A > a( new A() );
//use a
//std::unique_ptr deletes a

You don't leak memory if you use modern c++.
This thread is really becoming a very valuable reference for me (and hopefully others too!)

I completely wasn't aware garbage collection was *not* automatic in C++.

But wait, if I do use:


int b = 0;


and then use b all I want. Do I have to worry about garbage collecting such variables? Or do those get garbage collected automatically?

This thread is really becoming a very valuable reference for me (and hopefully others too!)

I completely wasn't aware garbage collection was *not* automatic in C++.

But wait, if I do use:


int b = 0;


and then use b all I want. Do I have to worry about garbage collecting such variables? Or do those get garbage collected automatically?

You only have to worry about memory in C++ when it is allocated via new (or malloc, if you're working with C). If you don't create the variable with new, you don't have to delete it. So yes, you can use b all you want and not worry about cleaning up. However, if you did the following, you would have to worry about cleaning up:


int* b = new int;
// Use b all you want, but be sure to delete it when you're done, or else memory will get leaked!
delete b;
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
You may find my articles of use.
Memory Management and general safety procedures.
Organizational guidelines including file naming etc.

You can ignore the naming conventions section in the second link if that is not your bag. Everyone has his or her own style.
The part following that (Structure) is generally more widely accepted as good practice, and I made an effort to explain why each guideline exists rather than just to spew them out.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


You may find my articles of use.
Memory Management and general safety procedures.
Organizational guidelines including file naming etc.

You can ignore the naming conventions section in the second link if that is not your bag. Everyone has his or her own style.
The part following that (Structure) is generally more widely accepted as good practice, and I made an effort to explain why each guideline exists rather than just to spew them out.


L. Spiro


Wow, thanks for those articles YogurtEmperor! I will definitely keep these as references.

One question about smart pointers though. I understand that anything you allocate with "new", you need to delete later on. And smart pointers automatically get garbage collected. But what if I declare a pointer like so:

b2Body * body;

Where I'm never actually using the "new" keyword, would this pointer be garbage collected like a normal variable or would I need to delete it or what?
Smart pointers aren't garbage collected. The different variants of smart pointers do different things to keep track of when something should be deleted, but garbage collection isn't what's going on here. Garbage collection is a process that inspects the heap and searches for reachable memory objects and ones that aren't and deletes the unreachable ones. Smart pointers, such as shared_ptr use something called reference counting which keeps track of how many things currently have access to the pointer. When the reference count reaches zero, the shared_ptr knows that nothing can access the pointer and deletes it.

It may seem like a subtle distinction, but it's very different from garbage collection. The key difference is that garbage collection actually spends time to inspect large portions of the heap and builds lists of what's reachable and what's not. shared_ptr maintains an internal reference counting mechanism that is appropriately modified on construction, copy construction, assignment, and destruction of the instances of the shared_ptr.

As far as your question is concerned, the pointer you've declared:

b2Body * body;

Is a variable that lives on the stack which is a pointer to b2Body. There's nothing special going on here and currently you've not used shared_ptr. body isn't garbage collected, or reference counted, or anything fancy like that. It's just standard stack frame allocation and deallocation when it scopes in and out.

However, if you later on perform a:

body = new b2Body();

There are several things that can happen. One thing that could happen is that you forget to ever put a delete in there. What happens is as soon as the scope of the variable body has ended, the stack memory for that pointer is deallocated but the heap object you allocated through the new is not. You've just leaked memory.

You could also add in all of the necessary deletes. This can be anything from just deleting right at the end of the scope if you don't need the object after that (in which case, you should have probably just put the entire object on the stack in the first place) or following all the places where the object's lifetime is relevant and finding when it dies and placing deletes there.

But, notice there's no garbage collection or reference counting sorcery going on here. You're using old school, manual heap allocations, where you have to do everything yourself. If you had used a shared_ptr() from the beginning, you wouldn't have to worry about those things (as much...). shared_ptr and many of the other smart pointers aren't perfect (shared_ptr can still leak if you aren't careful), but they are extremely convenient if you can afford to use them.

This topic is closed to new replies.

Advertisement