|
|
Hello,
I have a few questions regarding Memory Management in Visual C++. I am using Visual Studio .NET 2002 and as a sidenote I am creating a Win32 application that uses the DirectX API. I am compiling in Debug mode (not Release). If I create a Class, I generally make a constructor and destructor for each class. I know the constructor is called when the user creates (instantiates) a class object. When is the destructor called?
Do I need to do something to my class object to call the destructor? Or is this automated somehow?
Also, I want to be sure I don't have any memory leaks (releasing all COM objects and freeing all pointers). How do I specifically check to see that I have successfully done so in Visual Studio .NET?
Thank You,
CBerg
|
|
|
|
|
the destructor will be called when an object leaves its living scope,for example function returning. You should not try to call it directly,or the comiler may complains about that because it knows when to call the destructor. You should read some C++ textbooks to gain more about C++.
the second one: the return type of all COM interfaces is HRESULT,which is a 32bit integer. The first bit of it indicates whether an operation succeeded or failed: 0 for success and 1 for fail,so if the returing value is less than 0, you can know that the operation failed,otherwise success. Usually you can use the following macro which is defined in the Winerror.h:
#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
#define FAILED(Status) ((HRESULT)(Status)<0)
but for the IUnknown::Release,you should always get S_OK result.
|
|
|
|
|
Hi,
Just to add to what exRange said. If you allocate objects on the heap (through the keywork 'new'), then you are responsible for freeing the memory by calling delete. Generally, it is a good idea to allocate resources in the constructor and make sure they are freed in the destructor.
Keith
|
|
|
|
|
Essentially, there are three ways to create an object:
class Object {
public:
Object();
~Object();
};
Object GlobalObject;
void Function()
{
Object StackObject;
Object *HeapObject = new Object;
delete HeapObject;
} First, we have a class Object , with a constructor and a destructor. There are three instances of the class in the code: GlobalObject , StackObject , and HeapObject (which is a pointer).
Since GlobalObject is at file scope, the constructor for GlobalObject is called by the C++ runtime when the program starts, and its destructor when the program exits.
StackObject is created on the stack, inside the function Function . It's destructor is called when Function() exits. More precisely, the destructor is called when execution leaves the enclosing scope (the outermost braces "{" "}" of the function).
HeapObject is a pointer to an Object allocated on the heap using the new operator. In this case, the user (you the programmer) must explicitly destroy the object using the delete operator. The delete operator calls the destructor.
COM objects are slightly different. You 'allocate' COM objects using CoCreateInstance or one of the related functions, which return an interface pointer. All COM interfaces derive from the IUnknown interface, which has three methods: AddRef , Release , and QueryInterface . When you are done using a COM object, you release it by calling the Release method through its interface pointer.
Software Zen: delete this;
|
|
|
|
|
That was a beautiful answer! Thank You.
Do heap objects need to be called within functions, or can they be global as well?
When should I use a heap object rather than using a global or stackobject? As a sidenote, I am using C++ with DirectX to create different objects in my world space. I have implemented both the global object and heap objects, but I couldn't really tell a difference. Both versions of the object worked fine.
|
|
|
|
|
Iceberg76 wrote:
Thank You
You're welcome.
Iceberg76 wrote:
Do heap objects need to be called within functions, or can they be global as well?
Pointers to heap objects can be global, or can be passed from routine to routine as needed. The objects themselves reside on the heap, which in a sense is a global data structure.
Iceberg76 wrote:
When should I use a heap object rather than using a global or stackobject?
Using the heap is a good idea when you don't know how many objects you'll need. One time, you may only allocate one object. The next time, maybe you'll need ten. The heap lets you adapt to that kind of situation.
Global objects have their good and bad points. They are good, in that a global object is easy to access from a lot of points in your software. Unfortunately, that's also their weak point. Since they can be accessed from everywhere, your software can get pretty tangled up. You'll find out that you can't change this feature of the object, because that part of the application depends on it. It can make maintenance and debugging a nightmare.
Stack objects are useful when you know you only need the object for the duration of a given routine.
Software Zen: delete this;
|
|
|
|
|
Hey everyone,
I'm trying to learn C++ so take it easy one me, k?
I have a class called wrdrSE, and a dialog called IDD_WORDRAIDER_DIALOG. I want to use an instance of wrdrSE and call several functions within it. When the user click a button on IDD_WORDRAIDER_DIALOG, the button click events will create the instance, and call several functions within the instance. But, I am getting linking errors when I compile my project. Here are the errors:
Word RaiderDlg.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall wrdrSE::~wrdrSE(void)" (??1wrdrSE@@UAE@XZ)
Word RaiderDlg.obj : error LNK2001: unresolved external symbol "public: void __thiscall wrdrSE::Find(void)" (?Find@wrdrSE@@QAEXXZ)
Word RaiderDlg.obj : error LNK2001: unresolved external symbol "public: void __thiscall wrdrSE::CreateKeywords(class CString)" (?CreateKeywords@wrdrSE@@QAEXVCString@@@Z)
Word RaiderDlg.obj : error LNK2001: unresolved external symbol "public: __thiscall wrdrSE::wrdrSE(void)" (??0wrdrSE@@QAE@XZ)
-------------------------------
Some of the header for wrdrSE:
-------------------------------
// wrdrSE.h: interface for the wrdrSE class.
#include "wrdrSearchResults.h"
#include "wrdrSearchSettings.h"
class wrdrSE
{
public:
wrdrSE();
virtual ~wrdrSE();
public:
void CreateKeywords(CString Query);
void Find();
};
-------------------------------
here are parts of wrdrSE.cpp:
-------------------------------
// wrdrSE.cpp: implementation of the wrdrSE class.
#include "stdafx.h"
#include "Word Raider.h"
#include "wrdrSE.h"
#include "wrdrSearchResults.h"
#include "wrdrSearchSettings.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
void CreateKeywords(CString Query){
}
void Find(){
}
-------------------------------
Why am I getting these linking errors???
|
|
|
|
|
you must add the classname
void wrdrSE::CreateKeywords(CString sQ) {
}
and
void wrdrSE::Find(){
}
|
|
|
|
|
Try adding this to all your class function definitions in .cpp file:
void wrdrSE::CreateKeywords(CString Query){
}
|
|
|
|
|
|
Are these statements equivalent?
char *TextString
char TextString[]
Both declarations work with my program, but I'm not sure which is correct. Basically, I want to pass a string as a parameter, but when I define the function I don't really know the size of the string.
Thank You.
CBerg
|
|
|
|
|
Functionally there are the same excluding some obscure rules. Maybe one of the uber C++ people here will know.
One thing is that char *TextString says a pointer to a character where char TextString [] actually does imply an array.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
Specifically,
I am printing out text strings to my Display Window using DirectX. Basically I am storing a float variable into a text string:
char fpsString[] = "Fps: 0000.000000";
float fps;
fps = FrameCnt / TimeElapsed;
sprintf(fpsString, "Fps: %f \0", fps);
m_Font.Render(fpsString, 0, 0, g_Width, g_Height, DT_TOP | DT_RIGHT, 0xff000000);
that function is defined as...
void CDXFont::Render( char *TextString, int Xpos, int Ypos, int Width, int Height, DWORD Format, D3DCOLOR Color )
{
//
// Render the Font
//
Font->DrawText(
0,
TextString,
-1, // size of string or -1 indicates null terminating string
&Rect, // rectangle text is to be formatted to in windows coords
Format, // where to draw in viewport
Color); // Color of text.
}
Don't worry about the DirectX and COM stuff, but I am wondering the proper way to go about printing a string which is a float number. This number might be really big or even negative at times, so that is why my parameter is a pointer. Am doing this the wrong way? I also want to format this number so that it is only about 2 or 3 decimal precision instead of 6. How would I be able to do this in C++?
Thank You,
CBerg
|
|
|
|
|
The biggest problem in your code is that sprintf() may overflow the boundaries of fpsString if fps is large. You should use proper C++ strings instead of legacy C character arrays, e.g.
std::ostringstream fpsString;
fpsString << "Fps: " << fps;
m_font.Render(fpsString.str().c_str(), 0, 0, g_height, DT_TOP | DT_RIGHT, 0xff000000);
|
|
|
|
|
OH GOD NO!!!
std::ostringstream is slower than a dead man glued to the sidewalk.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
|
See my other post. Using stringstream just to avoid the buffer overrun issue can cause performance problems. snprintf was created just for this problem.
A while back someone had a problem with std::hash being very slow. It was discovered that he was generating his keys with stringstream. Once he switched over to something with less overhead, it was MUCH faster.
Don't get me wrong, stringstream is great. However in this case it is like using a 767 airliner for cropdusting.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
|
Thank You everybody.
I would like to mention that it appears snprintf() is limited to Unix. I am using Visual C++ .NET and I had to call _snprintf() for this to work.
I still had to be sure that my string declaration was fairly large to accomodate the whole number.
char fpsString[22];
But, I could easily change decimal precision using the _snprintf().
I'm not sure about the speed issue, but if someone else could confirm that would be nice.
CBerg
|
|
|
|
|
Woops, I forgot about that...
(Which is another reason to use stringstream due to badly designed C routines.)
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
char fpsString [80];
float fps;
fps = FrameCnt / TimeElapsed;
snprintf(fpsString, 80, "Fps: %f \0", fps);
1. Trying to sprintf to a string like you were doing might cause problems on some platforms.
2. As someone pointed out, the sprintf might overflow the buffer. snprintf works great to avoid this problem without using STL which has its share of problems.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
See here.
"The pointy end goes in the other man." - Antonio Banderas (Zorro, 1998)
|
|
|
|
|
first,in "afx.h" include "afxdb.h"
second declare global variable "CDatabase db;" and define "CString os="ODBC;DSN=MyDb;UID="user";PWD="mypassword";"in view
third,when i write"db.open(NULL,FALSE,FALSE,os);the result of compiling show there are 4 error.
why?
how to connect access database in vc++6.0?(the data source of ODBC done already)
|
|
|
|
|
You create a ODBC connection. Example: Name is MyDb.
The function is:
db.Open("MyDb");
If has User Name, Password:
db.Open("MyDb", FALSE, FALSE, "ODBC;UID=UserName;PWD=MyPassword");
Not use the char " in UserName And Password string
|
|
|
|
|