Sign in to follow this  

Memory tracker

This topic is 4271 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I would like to write a series of functions which I can use in my applications which can track current memory usage by the application (so I can identify memory leaks) and I would also like to be able to identify and catch exceptions. If this is possible, would someone please point me in the right direction. I realise it's not a menial task, but right now I dont even know where to start looking. This kind of cuntionality would be invaluble. Many thanks, TheBob

Share this post


Link to post
Share on other sites
The following is a simplified version of the code I use to perform memory tracking...


//-----------------------------------------------------------------------------
// File : MemoryLeakTracker.h
// Author : Shaun Dwane White
// Creation Date : 03-04-06
// Revision Date : 03-04-06
// Version : 1.0
//
// Notes : Header file for MemoryLeakTracker.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Header file inclusion guard.
//-----------------------------------------------------------------------------
#ifndef MEMORY_LEAK_TRACKER__H
#define MEMORY_LEAK_TRACKER__H

//-----------------------------------------------------------------------------
// Standard includes for this header file to work.
//-----------------------------------------------------------------------------
#include <windows.h>
#include <crtdbg.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>

//-----------------------------------------------------------------------------
// Microsoft specific compiler symbol, that is defined during DEBUG builds and
// undefined during RELEASE builds. This flag is used to ensure that the
// memory tracking macros are only defined in DEBUG builds.
//-----------------------------------------------------------------------------
#ifdef _DEBUG

//-----------------------------------------------------------------------------
// DEBUG Macros:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SNAP_HEAP:
// Takes a snap shot of the current debug heap. MUST be used in conjuntion
// with a following TEST_HEAP macro in the SAME code statement block.
//
// TEST_HEAP:
// Takes another snap shot of the debug heap and compares it with the previous
// snap shot obtained by the previous SNAP_HEAP macro. If there is a
// difference, then a message box will appear, warning you that a leak has
// occurred. The message box will also display the file and line number where
// the detection took place, as well as giving you the option to continue or
// abort the program.
//
// Notes:
// Simply detecting a leak is sufficient for my purposes, but you could alter
// the code easily to determine just how much bytes were leaked and in what
// heap etc. You can even obtain a dump of the heap statistics if you like...
// Just check out the _CrtMem... functions defined in "crtdbg.h" and explained
// in MSDN.
//
// Also note that the _CrtMem... functions are DEBUG only functions.
//-----------------------------------------------------------------------------
#define SNAP_HEAP *
{ *
_CrtMemState oldHeap; *
*
_CrtMemCheckpoint (&oldHeap); *
{

#define TEST_HEAP *
} *
_CrtMemState newHeap, heapDifference; *
_TCHAR msgBoxText [MAX_PATH + 1]; *
*
_CrtMemCheckpoint (&newHeap); *
if (_CrtMemDifference (&heapDifference, &oldHeap, &newHeap)) *
{ *
_sntprintf *
( *
msgBoxText, MAX_PATH, _TEXT ("Memory leak detected!\n\nIn file:\n%s\n\nAt line:\n%d\n\nExit process?"), *
_TEXT (__FILE__), __LINE__ *
); *
msgBoxText[MAX_PATH] = 0; *
if (MessageBox (0, msgBoxText, TEXT ("Memory Leak!!!"), MB_YESNO | MB_ICONWARNING) != IDNO) ExitProcess (EXIT_FAILURE); *
} *
}

//-----------------------------------------------------------------------------
// SNAP_HEAP_STATE (heap):
// Takes a snap shot of the debug heap and stores the result in "heap". This
// is a more flexible version of the SNAP_HEAP macro, because if "heap" is
// defined globally, then you don't necessarily have to perform a test in the
// same code block.
//
// TEST_HEAP_STATE (heap):
// Performs exactly like the TEST_HEAP macro, except it now tests the "heap"
// variable.
//
// Notes:
// These macros are more flexible than the previous pair, as it can detect
// memory leaks that occur across function calls. Useful for general
// programming issues as well as detecting leaks in DLLs (provided you perform
// the test in DllMain's DLL_PROCESS_ATTACH and DLL_PROCESS_DETACH cases).
//
// The variable "heap" MUST be of the type: _CrtMemState
//-----------------------------------------------------------------------------
#define SNAP_HEAP_STATE(heap) _CrtMemCheckpoint (static_cast<_CrtMemState *> (&heap));

#define TEST_HEAP_STATE(oldHeap) *
{ *
_TCHAR ___msgBoxText [MAX_PATH + 1]; *
_CrtMemState ___newHeap, ___heapDifference; *
*
_CrtMemCheckpoint (&___newHeap); *
if (_CrtMemDifference (&___heapDifference, static_cast<const _CrtMemState *> (&oldHeap), &___newHeap)) *
{ *
_sntprintf *
( *
___msgBoxText, MAX_PATH, _TEXT ("Memory leak detected!\n\nIn file:\n%s\n\nAt line:\n%d\n\nExit process?"), *
_TEXT (__FILE__), __LINE__ *
); *
___msgBoxText[MAX_PATH] = 0; *
if (MessageBox (0, ___msgBoxText, TEXT ("Memory Leak!!!"), MB_YESNO | MB_ICONWARNING) != IDNO) ExitProcess (EXIT_FAILURE); *
} *
}

//-----------------------------------------------------------------------------
// RELEASE Macros:
// Ensures that all memory tracking macros are omitted in RELEASE builds.
//-----------------------------------------------------------------------------
#else

#define SNAP_HEAP
#define TEST_HEAP

#define SNAP_HEAP_STATE(heap) 0;
#define TEST_HEAP_STATE(oldHeap) 0;

#endif // _DEBUG
#endif // MEMORY_LEAK_TRACKER__H




IMPORTANT NOTE!!! If you copy and paste the above code, you must turn all ending '*' characters into backslash characters '\'. For some reason
(my English keyboard I think), '\' characters don't print very well here.

Here is a source code example of how one would this code:


#include "MemoryLeakTracker.h"

#ifdef _DEBUG
_CrtMemState debugHeap;
#endif // _DEBUG

void MemoryLeakFunction (PBYTE memoryLeak)
{
if (memoryLeak) memoryLeak = new BYTE;
}

int main ()
{
PBYTE memoryLeakOne;
PBYTE memoryLeakTwo;

//----------------------------------------------------------------------------------------------------------------------------------------
// SNAP_HEAP, TEST_HEAP example:
//----------------------------------------------------------------------------------------------------------------------------------------
SNAP_HEAP
{
memoryLeakOne = new BYTE;
}
TEST_HEAP

//----------------------------------------------------------------------------------------------------------------------------------------
// SNAP_HEAP_STATE, TEST_HEAP_STATE example:
//----------------------------------------------------------------------------------------------------------------------------------------
SNAP_HEAP_STATE (debugHeap)
MemoryLeakFunction (memoryLeakTwo);
TEST_HEAP_STATE (debugHeap)

return EXIT_SUCCESS;
}




And here is a simplified version of the code I use for handling exceptions:


//-----------------------------------------------------------------------------
// File : SimpleExceptionHandler.h
// Author : Shaun Dwane White
// Creation Date : 03-04-06
// Revision Date : 03-04-06
// Version : 1.0
//
// Notes : Header file for SimpleExceptionHandler.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Header file inclusion guard.
//-----------------------------------------------------------------------------
#ifndef SIMPLE_EXCEPTION_HANDLER__H
#define SIMPLE_EXCEPTION_HANDLER__H

//-----------------------------------------------------------------------------
// Standard include for this header file to work.
//-----------------------------------------------------------------------------
#include <windows.h>

//-----------------------------------------------------------------------------
// Exception structure declarations:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// General EXCEPTION structure declaration:
//
// This structure is thrown when a general exception is raised and is used as
// a BASE structure for all other types of exceptions.
//-----------------------------------------------------------------------------
struct EXCEPTION
{
LPCTSTR ITS_MSG; // The exception's message string.
LPCTSTR ITS_FILE; // The name of the file in which the exception is thrown.
DWORD itsLine; // The line number where the exception was thrown.
PVOID itsParam; // Extra parameter for future expansion.

EXCEPTION (LPCTSTR, LPCTSTR, DWORD, PVOID = 0);
};

//-----------------------------------------------------------------------------
// MEMORY_EXCEPTION structure declaration:
//
// This structure is specifically thrown when memory can no longer be allocated.
//-----------------------------------------------------------------------------
struct MEMORY_EXCEPTION : public EXCEPTION
{
MEMORY_EXCEPTION (LPCTSTR, LPCTSTR, DWORD, PVOID = 0);
};

//-----------------------------------------------------------------------------
// You could introduce further exception structures here in a similar way, like
// DRIVE_EXCEPTION for disk drive problems, or GRAPHICS_EXCEPTION for video
// card problems etc.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Exception structure inlined implementations:
//
// These structures are pretty simple, so we may as well inline their
// implementations here in this header file. They'll perform a bit quicker too!
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// General EXCEPTION structure implementation:
//-----------------------------------------------------------------------------
inline EXCEPTION::EXCEPTION (LPCTSTR MSG, LPCTSTR FILE, DWORD line, PVOID param):
ITS_MSG (MSG),
ITS_FILE (FILE),
itsLine (line),
itsParam (param)
{
}

//-----------------------------------------------------------------------------
// MEMORY_EXCEPTION structure implementation:
//-----------------------------------------------------------------------------
inline MEMORY_EXCEPTION::MEMORY_EXCEPTION (LPCTSTR MSG, LPCTSTR FILE, DWORD line, PVOID param):
EXCEPTION (MSG, FILE, line, param)
{
}

#endif // SIMPLE_EXCEPTION_HANDLER__H





And finally, here is a source code example of how one would use this simple exception handler:


#include "ExceptionHandler.h"

#include <stdio.h>
#include <tchar.h>

void PrintException (const EXCEPTION &EXCEPTION)
{
_tprintf ("ITS_MSG\t\t%s\n", EXCEPTION.ITS_MSG);
_tprintf ("ITS_FILE\t%s\n", EXCEPTION.ITS_FILE);
_tprintf ("itsLine\t\t%u\n", EXCEPTION.itsLine);
_tprintf ("itsParam\t%s\n\n", EXCEPTION.itsParam);
}

int main ()
{
//-----------------------------------------------------------------------------
// Throw and catch a general exception:
//
// Note:
// The pre-defined symbols __FILE__ is turned into a string which contains the
// filename of the current file by the compiler during compilation.
//
// The pre-defined symbols __LINE__ is tured into the current code line number
// by the compiler during compilation.
//-----------------------------------------------------------------------------
try
{
throw EXCEPTION (_TEXT ("General Exception Thrown!"), __FILE__, __LINE__);
}
catch (EXCEPTION &EXCEPTION)
{
PrintException (EXCEPTION);
}
catch (...)
{
puts ("An unknown exception has been caught!");
}

//-----------------------------------------------------------------------------
// Throw and catch a memory exception:
//
// Note:
// If you specifically wanted to catch memory exception, you must place them
// ABOVE the code where general or undefined exceptions would be caught.
//-----------------------------------------------------------------------------
try
{
throw MEMORY_EXCEPTION (_TEXT ("Out Of Memory!"), __FILE__, __LINE__);
}
catch (MEMORY_EXCEPTION &MEMORY_EXCEPTION)
{
PrintException (MEMORY_EXCEPTION);
}
catch (EXCEPTION &EXCEPTION)
{
PrintException (EXCEPTION);
}
catch (...)
{
puts ("An unknown exception has been caught!");
}

return 0;
}





Please feel free to copy and paste the code if it suits your needs.

I hope this helps!

[Edited by - TerrorFLOP on April 3, 2006 12:53:56 AM]

Share this post


Link to post
Share on other sites
If you're using Visual C++, you could also use their memory trakcer with

#include <crtdbg.h> // in the stdafx.h
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // in the main entry point of your program

It will prints in the debug output of visual a list of all the memory links, with an allocID. With this allocID, you can then re-execute the program, and break when it is reached, using this line :

_CrtSetBreakAlloc(5031); // where 5031 is the allocID reported by the previous execution

Share this post


Link to post
Share on other sites
Quote:
Original post by TerrorFLOP
...


You mix C and C++ code. The cast static_cast is not available in C, the headers stdlib.h and stdio.h aren't available in C++. There is some other stuff which also is only in one of the languages. Your code mostly looks like C with some stuff borrowed from C++, but this isn't standard. If it's supposed to be C++ code then you should not use the C functions like _sntprintf, _tprintf etc. Instead you should use the C++ standard library (You would need streams). Also you know in C++ (not sure about C) you are not allowed (well it might just result in undefined behavior, can't remember, but it's not guareented to act like a normal variable) to start your variable names with __ (two underscores), since those are reserved for the compiler..

Share this post


Link to post
Share on other sites
I've been mixing C and C++ for years.

It's ALL perfectly legal under MS Visual C++ 6.0.

As my old grandma used to say...

'If you can, have the best of both worlds...'

I tend to use TRIPLE underscoring in my #define symbols.

This is my OWN programming style (again perfectly legal), which ensures I don't have a symbol clash with other #defines. And since some symbols have DOUBLE underscoring... I thought TRIPLE underscoring would be a wise precaution, considering that #define symbols cannot be namespaced.

Again, my own style... That suits me just fine thx!

BTW... Double underscoring or indeed single underscoring... Or having varibles and symbols that start with TEN underscores is ALL prefectly legal (C/C++ are very flexible), so long as you don't have a clash with an already defined variable or symbol.

Share this post


Link to post
Share on other sites
Quote:
Original post by Omaha
stdio.h, stdlib.h, etc., as well as the *printf family of functions are all perfectly legal C++.


stdio.h, stdlib.h, etc are NOT part of C++. You're thinking of cstdio, cstdlib, etc. Which are the C++ headers that support the C89 standard library.

Share this post


Link to post
Share on other sites
Quote:
Original post by TerrorFLOP
I've been mixing C and C++ for years.

It's ALL perfectly legal under MS Visual C++ 6.0.


VC++6 is a poor, poor example of a C++ compiler. It was even released before C++ was standardized.

Quote:

I tend to use TRIPLE underscoring in my #define symbols.

This is my OWN programming style (again perfectly legal), which ensures I don't have a symbol clash with other #defines. And since some symbols have DOUBLE underscoring... I thought TRIPLE underscoring would be a wise precaution, considering that #define symbols cannot be namespaced.

Again, my own style... That suits me just fine thx!

BTW... Double underscoring or indeed single underscoring... Or having varibles and symbols that start with TEN underscores is ALL prefectly legal (C/C++ are very flexible), so long as you don't have a clash with an already defined variable or symbol.


It's really not as legal as you claim it is. If you check the C++ standard, it clearly states that identifiers that start with a _ are reserved for the implementation to use as it sees fit (and by implementation, they mean the compiler / standard library writer. Not you.)

Although, if you're using VC6, you're expressing that you don't really care about being standards conforming anyway. I would strongly recommend you upgrade to something like VC8 (the express version is free, so there's really little excuse for people to still be using VC6. It amazes me how many beginners get ahold of VC6, considering it's not free.)

Share this post


Link to post
Share on other sites
Quote:
Original post by TerrorFLOP
BTW... Double underscoring or indeed single underscoring... Or having varibles and symbols that start with TEN underscores is ALL prefectly legal (C/C++ are very flexible), so long as you don't have a clash with an already defined variable or symbol.
Quote:
C++ Standard, Final Draft, Section 2.10, Paragraph 2
In addition, identifiers containing a double underscore (_ _) or beginning with an underscore and an uppercase letter are reserved for use by C++ implementations and standard libraries and shall not be used otherwise; no diagnostic is required.

Just because your compiler lets you do it doesn't make it legal. Identifiers containing double underscores are reserved for C++ compiler writers and standard library writers. This is for your own protection. Don't use such identifiers yourself. One day they will bite you.

Quote:
Original post by RDragon1
stdio.h, stdlib.h, etc are NOT part of C++. You're thinking of cstdio, cstdlib, etc. Which are the C++ headers that support the C89 standard library.
Quote:
C++ Standard, Final Draft, Annex D, Section 5, Paragraph 1
For compatibility with the Standard C library, the C++ Standard library provides the 18 C headers, as shown in Table 101:
Table 101 — C Headers
<assert.h> <iso646.h> <setjmp.h> <stdio.h> <wchar.h>
<ctype.h> <limits.h> <signal.h> <stdlib.h> <wctype.h>
<errno.h> <locale.h> <stdarg.h> <string.h>
<float.h> <math.h> <stddef.h> <time.h>

They're deprecated as noNchaoTic said, but not removed, at least in the final draft of the standard.

Σnigma

Share this post


Link to post
Share on other sites
I hear what you're saying guys...

But I'm not really one that conforms to standards... Well, not when it comes to my own code anyway.

So long as the code works and runs without any bugs, then that’s fine by me.

Standards are all well and good and I've nothing against them... So, even though I have no intention of changing my style (which works for me and besides, its a habit I've had for YEARS now), I'll submit more standardized code to future threads next time.

No point having other peeps picking up my bad habits LOL!

I keep forgetting 'standards' is such a contentious issue here :-(

Share this post


Link to post
Share on other sites
Quote:
Original post by TerrorFLOP
I've been mixing C and C++ for years.

It's ALL perfectly legal under MS Visual C++ 6.0.

As my old grandma used to say...

'If you can, have the best of both worlds...'

I tend to use TRIPLE underscoring in my #define symbols.

This is my OWN programming style (again perfectly legal), which ensures I don't have a symbol clash with other #defines. And since some symbols have DOUBLE underscoring... I thought TRIPLE underscoring would be a wise precaution, considering that #define symbols cannot be namespaced.

Again, my own style... That suits me just fine thx!

BTW... Double underscoring or indeed single underscoring... Or having varibles and symbols that start with TEN underscores is ALL prefectly legal (C/C++ are very flexible), so long as you don't have a clash with an already defined variable or symbol.


Then your a very naughty boy! :-)

Share this post


Link to post
Share on other sites
Quote:
Original post by TerrorFLOP
I hear what you're saying guys...

But I'm not really one that conforms to standards... Well, not when it comes to my own code anyway.

So long as the code works and runs without any bugs, then that’s fine by me.

Standards are all well and good and I've nothing against them... So, even though I have no intention of changing my style (which works for me and besides, its a habit I've had for YEARS now), I'll submit more standardized code to future threads next time.

No point having other peeps picking up my bad habits LOL!


Fine, just remind me never to hire you and we're good :)

Share this post


Link to post
Share on other sites
@TerrorFLOP: It might be easier to overload new/delete with your own implmentation, that way you don't have to get the "user", aka program to put in __LINE__, __FILE__ stuff all over.

So you don't have to have this in your code:
SNAP_HEAP
{
memoryLeakOne = new BYTE;
}
TEST_HEAP

You'd just have the memoryLeakOne = new BYTE; and it would do the SNAP_HEAP/TEST_HEAP in the new function for you. You can also have, in debug mode, your new function take 3 variables, the size, __FILE__ and __LINE__ for you.

Just a thought to improve your code and make it easier to use (this way no one can get lazy and skip over your stuff to get things done faster). Even when coding for myself I like to think ahead (as I get lazy too) and figure out how to avoid having other programmers improperly use my code as best as possible (nothing is fool proof).

Best of luck. Oh and do yourself a favor and get the free version of Visual Studios. I literally tossed my copy of VC6 out (have 2k3 but I like it).

Share this post


Link to post
Share on other sites
Quote:
Original post by TerrorFLOP
So long as the code works and runs without any bugs, then that’s fine by me.
Maybe you haven't noticed the bugs caused by your sloppy misunderstandings of the language, but that doesn't mean things are ok.

[Edited by - Promit on April 3, 2006 10:37:46 PM]

Share this post


Link to post
Share on other sites
Yeah Mike...

I already have overloaded new and new [] operators that automatically throw out exceptions if memory cannot be allocated. I have even extended upon this to allow allocated memory to be aligned. Useful when performing optimized memory operations (like MMX and SIMD).

I have a variety of techniques when it comes to exceptions and debugging in general.

I just thought submitting the code I wrote for my overloaded new operators might confuse the person I was trying to help (LOL... Some may say I've done a pretty good job already!).

I know macros are VERY messy, hence all this fuss about underscores, but they get the job done. As I said before, you can't namespace macros, that's WHY I resorted to using underscores in my macros, in order to provide some protection against a possible symbol clash... Microsoft tends to use two underscores for their symbols, so I used three as a precaution. Hell I even GUID my inclusion guards too i.e.;

#define ___HEADER_FILE__H__B562207D_F37E_4091_B417_B6BC562A8269

just to be sure. The Microsoft Visual C++ compiler actually generates inclusion guards in much the same way (that's where I got the idea from), if you create MFC applications.

And with regards to macro implementation, consider the simple situation...

#define ___MACRO(argument) { int integer = atoi (static_cast<PSTR> (argument)); ... }

In the highly unlikely, but possible off chance that a user might make the following mistake;

___MACRO (integer)

the program will crash. Hence why I would write the macro as follows;

#define ___MACRO(argument) { int ___integer = atoi (static_cast<PSTR> (argument)); ... }

just to provide some insurance against this. Of course, the user could still crash the program by using ___MACRO (___integer), but since this thread has already made it clear that underscores are NOT standardized, that's why I've elected to use them in this way.

Anyway, as I said before, macros are VERY dangerous... But I still find them useful, in conjunction with more modern standard methods, especially for debugging and profiling.

And I guess they may seem quite quaint to people these days, considering that they're been dropped from the C# language... I even hear C# has dropped templates too... And I LOVE templates :-(

Anyway, I hope I cleared up some previous confusion.

And yes Mike, thanks for that tip on upgrading my compiler. I'm sure I will soon... One day, but I still like my VC6.

Promit, if the code works, and you've tested it quite thoroughly, then it works yes?

I doubt underscoring your variables, although highly un-standard (and obviously detested by some), will introduce 'bugs' into your code.

At the end of the day, this thread (which has deviated some) has raised issues which is more about style and programming practise (i.e. to write or not to write standard code) than about syntax.

If my compiler compiles my program without making a fuss... Then I would like to think that it did so because it was syntactically 'correct', even though some may frown upon the 'style' of the program itself.

Share this post


Link to post
Share on other sites
Quote:
Original post by TerrorFLOP
And yes Mike, thanks for that tip on upgrading my compiler. I'm sure I will soon... One day, but I still like my VC6.

You might like your VC6, but I also liked Windows 3.1. The problem is both are outdated (almost equally, not in years, but in terms of new stuff). Expect to get thousands of errors when swithing because of your non-standard code, because you only cared about making your code work on VC6.

Quote:
Promit, if the code works, and you've tested it quite thoroughly, then it works yes?

I'm not Promit, but will answer anyway. No, there are cases where you wont introduce the bug until you hit just the right conditions, might be rand() returning max two times in a row. Also if code compiles on VC6 that most likely means your code is non-standard[evil] (well not actually, but there is a pretty big chance, especially when using for-loops).

Quote:
I doubt underscoring your variables, although highly un-standard (and obviously detested by some), will introduce 'bugs' into your code.

You are correct, it's very unlikely to introduce errors, but why not write standard code if it doesn't take any more effort?

Quote:
At the end of the day, this thread (which has deviated some) has raised issues which is more about style and programming practise (i.e. to write or not to write standard code) than about syntax.

So you think of it as "style and programming practice" to choose to use C code in the middle of a C++ file? What if my compiler supported Lisp in my C++ file would it also just be my style to write lisp inside C++ functions? C and C++ are closer so it doesn't seem as bad, but they are two different languages, and VC6 only partially supports the latter.

Quote:
If my compiler compiles my program without making a fuss... Then I would like to think that it did so because it was syntactically 'correct',

I like to believe that if my compiler gives me warnings, it's just a way to say thank you. Consider that VC6 was released before C++ was standarized, you can write VC6 C++ code or C++ code, two kinds of code which looks a lot like each other, but have lots of differences.

Quote:
even though some may frown upon the 'style' of the program itself.

I must agree that the *printf functions are ugly, but that is only my opinion and there are nothing wrong with using them, just like there is nothing wrong with programming procedurally in C++.

This is not to say that VC6 is a bad product or your code is bad. Your code is made for VC6 and as long as it stays on that compiler it will most likely not cause any problems. VC6 was released before the standarization of C++, so it had virtually no chance of conforming to the current C++ standard, that doesn't change the fact that it's outdated though.

Share this post


Link to post
Share on other sites
Quote:
Original post by TerrorFLOP
If my compiler compiles my program without making a fuss... Then I would like to think that it did so because it was syntactically 'correct', even though some may frown upon the 'style' of the program itself.


Or that it may not compile on any other platform, or other compiler, or even different version of the same compiler. There's no telling the amount of headaches and hassles you could go through by intentionally violating the standards, since the compiler should be safe to assume that a program is standard-conforming, and if it's not, then you're just asking for trouble, when you have the alternate of being guaranteed that trouble not exist.

Share this post


Link to post
Share on other sites
Quote:
Original post by CTar
I must agree that the *printf functions are ugly, but that is only my opinion and there are nothing wrong with using them, just like there is nothing wrong with programming procedurally in C++.


They're more than just ugly, they're downright dangerous to use. If you look at modern C++ design and programming practices, there is a huge shift towards using facilities that make it nearly impossible to write dangerous code. One great thing about C++ streams over C printf-like statements is that it's a lot harder to make a mistake without the compiler catching it. Plus, C++ streams are extensible and all of that, so not only are they much, much safer, they're much more flexible, too.

Quote:

This is not to say that VC6 is a bad product or your code is bad. Your code is made for VC6 and as long as it stays on that compiler it will most likely not cause any problems. VC6 was released before the standarization of C++, so it had virtually no chance of conforming to the current C++ standard, that doesn't change the fact that it's outdated though.


VC6 -is- a bad product in 2006. We don't live in 1998 anymore, and we should let go of the past in favor of making programs safer and easier to write. There's virtually no reason for anybody to be using VC6 anymore, especially for writing new code.

Share this post


Link to post
Share on other sites
Quote:
Original post by RDragon1
They're more than just ugly, they're downright dangerous to use. If you look at modern C++ design and programming practices, there is a huge shift towards using facilities that make it nearly impossible to write dangerous code. One great thing about C++ streams over C printf-like statements is that it's a lot harder to make a mistake without the compiler catching it. Plus, C++ streams are extensible and all of that, so not only are they much, much safer, they're much more flexible, too.

I agree, they are in-secure, in many cases in-efficient, not type-safe etc., but they are not wrong to use, I would also suggest streams.

Quote:

Quote:

This is not to say that VC6 is a bad product or your code is bad. Your code is made for VC6 and as long as it stays on that compiler it will most likely not cause any problems. VC6 was released before the standarization of C++, so it had virtually no chance of conforming to the current C++ standard, that doesn't change the fact that it's outdated though.


VC6 -is- a bad product in 2006. We don't live in 1998 anymore, and we should let go of the past in favor of making programs safer and easier to write. There's virtually no reason for anybody to be using VC6 anymore, especially for writing new code.


VC6 is not a bad program for writing the kind of "C++" it supports, neither is it bad for compiling older code. It's bad for writing C++ code though. Noone should start a new project using VC6 today.

Share this post


Link to post
Share on other sites
Ok ok...

You guys have got me convinced about upgrading my compiler.

If there are free upgrades available out there, then perhaps its time to move on.

But I'm sure some of you will understand the reluctance to move on, when you've gotten used to a particular product over a long time. Hell, it took me some time to get used to VC++6 from an old Borland C++ compiler. And I even have Visual Studio .NET (2004 edition I think), which I didn't like because I felt it had WAY too many unnecessary features.

But yeah... Perhaps it's time to upgrade... I just hope I can still use templates and macros... Even though macros are a right pain in the ass!

Share this post


Link to post
Share on other sites
Quote:
Original post by TerrorFLOP
Ok ok...

You guys have got me convinced about upgrading my compiler.

If there are free upgrades available out there, then perhaps its time to move on.

But I'm sure some of you will understand the reluctance to move on, when you've gotten used to a particular product over a long time. Hell, it took me some time to get used to VC++6 from an old Borland C++ compiler. And I even have Visual Studio .NET (2004 edition I think), which I didn't like because I felt it had WAY too many unnecessary features.

But yeah... Perhaps it's time to upgrade... I just hope I can still use templates and macros... Even though macros are a right pain in the ass!


Upgrade to VC8 (VS2005) - you can get VC++ Express 2005 for free from microsoft (compiler + IDE). Of course you can still use templates - VC6 is lacking in it's support of templates, and every version since then (7.0, 7.1, 8.0+) has much better standards compliance.

Share this post


Link to post
Share on other sites

This topic is 4271 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this