Releasing IDispatch pointer - visual-c++

Quote from IUnknown->Release() documentation:
"Notes to Callers
Call this method when you no longer need to use an interface pointer. If you are writing a method that takes an in-out parameter, call Release on the pointer you are passing in before copying the out-value on top of it."
1.#rc variable is equal to 1 after calling pDocument->Release() in the code below. Should I call Release twice for pDocument?
2.In which cases refence count for IDispatch is increased?
3.Does reference count for IDispatch increase when I pass it to my function as a pointer?
4.I have tens of IDispatch* objects, so what if I forget to Release() any of them? Memory leak?
5.Is there any easy way to release all IDispatch* or I have to release them only manually?
AutoWrap(DISPATCH_METHOD, &result.GetVARIANT(), pDocuments, TEXT("Close"), 1, saveChanges.GetVARIANT());
AutoWrap(DISPATCH_METHOD, &result.GetVARIANT(), pWApp, TEXT("Quit"), 0);
//Finalizing
if (pWApp)
{
pWApp->Release();
pWApp = NULL;
}
if (pDocuments)
{
ULONG rc = pDocuments->Release();
pDocuments = NULL;
}
if (pActiveDocument)
{
pActiveDocument->Release();
pActiveDocument = NULL;
}

1.#rc variable is equal to 1 after calling pDocument->Release() in the code below. Should I call Release twice for pDocument?
No. It means someone else also holds a reference to this object, and they wouldn't be amused if you get the object to delete itself right from under them.
2.In which cases refence count for IDispatch is increased?
When you call AddRef on it, or on any other interface pointer referring to the same object.
3.Does reference count for IDispatch increase when I pass it to my function as a pointer?
No, not automatically. The function, of course, is free to AddRef it, and would do so if needs to store the pointer somewhere so it could be used after the function returns.
4.I have tens of IDispatch* objects, so what if I forget to Release() any of them? Memory leak?
Yes. The same thing that happens when you forget to free something you've malloced, or delete something you've newed, or fclose something that you've fopened.
5.Is there any easy way to release all IDispatch* or I have to release them only manually?
Look at smart pointers, e.g. CComPtr or _com_ptr_t.

Related

Code analysis C26408 — Replacing the m_pszHelpFilePath variable in InitInstance

In my application's InitInstance function, I have the following code to rewrite the location of the CHM Help Documentation:
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
free((void*)m_pszHelpFilePath);
m_pszHelpFilePath = _tcsdup(strHelp);
It is all functional but it gives me a code analysis warning:
C26408 Avoid malloc() and free(), prefer the nothrow version of new with delete (r.10).
When you look at the official documentation for m_pszHelpFilePath it does state:
If you assign a value to m_pszHelpFilePath, it must be dynamically allocated on the heap. The CWinApp destructor calls free( ) with this pointer. You many want to use the _tcsdup( ) run-time library function to do the allocating. Also, free the memory associated with the current pointer before assigning a new value.
Is it possible to rewrite this code to avoid the code analysis warning, or must I add a __pragma?
You could (should?) use a smart pointer to wrap your reallocated m_pszHelpFilePath buffer. However, although this is not trivial, it can be accomplished without too much trouble.
First, declare an appropriate std::unique_ptr member in your derived application class:
class MyApp : public CWinApp // Presumably
{
// Add this member...
public:
std::unique_ptr<TCHAR[]> spHelpPath;
// ...
};
Then, you will need to modify the code that constructs and assigns the help path as follows (I've changed your C-style cast to an arguably better C++ cast):
// First three (almost) lines as before ...
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
free(const_cast<TCHAR *>(m_pszHelpFilePath));
// Next, allocate the shared pointer data and copy the string...
size_t strSize = static_cast<size_t>(strHelp.GetLength() + 1);
spHelpPath std::make_unique<TCHAR[]>(strSize);
_tcscpy_s(spHelpPath.get(), strHelp.GetString()); // Use the "_s" 'safe' version!
// Now, we can use the embedded raw pointer for m_pszHelpFilePath ...
m_pszHelpFilePath = spHelpPath.get();
So far, so good. The data allocated in the smart pointer will be automatically freed when your application object is destroyed, and the code analysis warnings should disappear. However, there is one last modification we need to make, to prevent the MFC framework from attempting to free our assigned m_pszHelpFilePath pointer. This can be done by setting that to nullptr in the MyApp class override of ExitInstance:
int MyApp::ExitInstance()
{
// <your other exit-time code>
m_pszHelpFilePath = nullptr;
return CWinApp::ExitInstance(); // Call base class
}
However, this may seem like much ado about nothing and, as others have said, you may be justified in simply supressing the warning.
Technically, you can take advantage of the fact that new / delete map to usual malloc/free by default in Visual C++, and just go ahead and replace. The portability won't suffer much as MFC is not portable anyway. Sure you can use unique_ptr<TCHAR[]> instead of direct new / delete, like this:
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
std::unique_ptr<TCHAR[]> str_old(m_pszHelpFilePath);
auto str_new = std::make_unique<TCHAR[]>(strHelp.GetLength() + 1);
_tcscpy_s(str_new.get(), strHelp.GetLength() + 1, strHelp.GetString());
m_pszHelpFilePath = str_new.release();
str_old.reset();
For robustness for replaced new operator, and for least surprise principle, you should keep free / strdup.
If you replace multiple of those CWinApp strings, suggest writing a function for them, so that there's a single place with free / strdup with suppressed warnings.

Accessing an atomic member of a class held by a shared_ptr

I'm trying to create a small class that will allow me to facilitate a communication between two threads.
Those threads most probably will outlive the context in which the above mentioned class was created as they are queued onto a thread pool.
What I have tried so far (on coliru as well):
class A
{
public:
A(int maxVal) : maxValue(maxVal) {}
bool IsOverMax() const { return cur >= maxValue; }
void Increase() { cur++; }
private:
const int maxValue;
atomic_int cur{ 0 };
};
possible usage:
void checking(const shared_ptr<A> counter)
{
while(!counter->IsOverMax())
{
cout<<"Working\n"; // do work
std::this_thread::sleep_for(10ms);
}
}
void counting(shared_ptr<A> counter)
{
while (!counter->IsOverMax())
{
cout<<"Counting\n";
counter->Increase(); // does this fall under `...uses a non-const member function of shared_ptr then a data race will occur`? http://en.cppreference.com/w/cpp/memory/shared_ptr/atomic
std::this_thread::sleep_for(9ms);
}
}
int main()
{
unique_ptr<thread> t1Ptr;
unique_ptr<thread> t2Ptr;
{
auto aPtr = make_shared<A>(100); // This might be out of scope before t1 and t2 end
t1Ptr.reset(new thread(checking, aPtr)); // To simbolize that t1,t2 will outlive the scope in which aPtr was originaly created
t2Ptr.reset(new thread(counting, aPtr));
}
t2Ptr->join();
t1Ptr->join();
//cout<< aPtr->IsOverMax();
}
The reason I'm concerned is that the documentation says that:
If multiple threads of execution access the same std::shared_ptr object without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur unless all such access is performed through these functions, which are overloads of the corresponding atomic access functions (std::atomic_load, std::atomic_store, etc.)
So Increase is a non const function, are the copies of aPtr are the same std::shared_ptr for this context or not ?
Is this code thread-safe?
Would this be OK for a non atomic object (say using an std::mutex to lock around reads and writes to a regular int)?
In any case why?
So Increase is a non const function, are the copies of aPtr are the same std::shared_ptr for this context or not ?
At std::thread creation, aPtr is passed by value. Therefore, it is guaranteed that:
You don't introduce a data race since each thread gets its own instance of shared_ptr (although they manage the same object A).
The documentation you are referring to describes a scenario whereby multiple threads operate on the same shared_ptr instance.
In that case, only const member functions can be called (see below), or synchronization is required.
shared_ptr reference-count is incremented before aPtr goes out of scope in main
So yes, this is a correct way to use shared_ptr.
Is this code thread-safe?
Your code does not introduce a data race, neither with access to shared_ptr instances, nor with access to the managed object A.
This means that there are no conflicting, non-atomic, read and write operations to the same memory location performed by multiple threads.
However, keep in mind that, in checking(), the call to IsOverMax() is separated from the actual work that follows
(Increase() could be called by the second thread after IsOverMax() but before 'do work'). Therefore, you could 'do work' while cur has gone over its maximum.
Whether or not that is a problem depends on your specification, but it is called a race condition which is not necessarily a programming error (unlike a data race which causes undefined behavior).
Would this be OK for a non atomic object (say using an std::mutex to lock around reads and writes to a regular int)?
cur can be a regular int (non-atomic) if you protect it with a std::mutex. The mutex must be locked for both write and read access in order to prevent a data race.
One remark on calling const member functions on objects shared by multiple threads.
The use of const alone does not guarantee that no data race is introduced.
In this case, the guarantee applies to shared_ptr const member functions, because the documentation says so.
I cannot find in the C++ standard whether that guarantee applies to all const member functions in the Standard Library
That documentation is talking about the member functions of shared_ptr, not the member functions of your class. Copies of shared_ptr objects are different objects.
I believe the code is thread safe, because the only changing variable written and read on different threads is cur, and that variable is atomic.
If cur was not atomic and access to it in both Increase() and IsOverMax() was protected by locking a std::mutex, that code would also be thread safe.

pin_ptr & PtrToStringChars vs. StringToHGlobalAnsi: Why does PtrToStringChars var loose its value?

I am using C++/CLI and I want to call the function WNetAddConnection2 from Windows Networking.
First, I know that C++/CLI is not the language of choice for my work, but I have no possibility to change that right now and e.g. use C# instead.
The problem now is, that this function takes wchar_t*, so I need to convert System::String^ to wchar_t*.
Solution 1): use pin_ptr and PtrToSTringChars from vcclr.h
Solution 2): use StringToHGlobalUni. (The title mentions StringHToGlobalAnsi because more people are searching for that so they might find this post and it's answers faster).
I have found out that both solutions work. But #1 does not really. I have put the WNet-functions into a ref class CWNetShare with following constructor:
CWNetShare::CWNetShare (String^ i_sLocalDrive, ...) {
pin_ptr<const wchar_t> wszTemp;
wszTemp = PtrToStringChars(i_sLocalDrive);
m_wszLocalDrive = const_cast<wchar_t*>(wszTemp);
where m_wszLocalDrive is a private CWNetShare member of type wchar_t*.
The real problem: while calling the constructor by m_oWNetShare = gcnew CWNetShare from a Winform class constructor (I know, C++/CLI and Winforms...), everything seems fine. The string i_sLocalDrive and others are converted and assigned correctly. But when accessing m_oWNetShare later, the values in all m_wsz... variables are lost. It looks like the object was moved around by the GC.
Therefore I have made a test:
ref class CManaged {
public:
wchar_t* m_wszNothing;
wchar_t* m_wszPinned;
wchar_t* m_wszMarshal;
System::String^ m_sTest;
CManaged ()
{
m_sTest = "Hello";
m_wszNothing = L"Test";
pin_ptr<const wchar_t> wszTemp;
wszTemp = PtrToStringChars(m_sTest);
m_wszPinned = const_cast<wchar_t*>(wszTemp);
m_wszMarshal = static_cast<wchar_t*>(System::Runtime::InteropServices::Marshal::StringToHGlobalUni (m_sTest).ToPointer());
}
};
Again a winform with m_oManaged = gcnew CManaged; in its constructor. When accessing m_oManaged later, then if m_oManaged was not moved, m_wszPinned is ok.
But after GCing, it's showing nonsense. BUT m_wsznothing keeps it's value, so it's not a problem of wchar_t*, but of the pin_ptr somehow. The address of m_oManaged has changed, but the address of m_wszPinned is the same, so why is the value lost then?
What is going wrong here?
Does pin_ptr and PtrToSTringChars have a use at all then?
I'm using marshalling now, which works.
PtrToStringChars is literally that: a pointer to the character array that the String^ holds internally.
When you're saving that pointer, it's a pointer to a managed object that the garbage collector is allowed to move. You're only guaranteed that it won't move for as long as the pin_ptr exists, which you're not keeping around. As soon as the pin_ptr no longer exists, the garbage collector is free to move the managed object around, and your pointer now points at some other object, somewhere in the managed heap.
Use PtrToStringChars if you're going to call an unmanaged function, and you don't need the string to persist beyond that one API call (and the unmanaged function doesn't keep a reference to the string). Use StringToHGlobalUni if you need to keep the unmanaged string around long-term.

Memory release while reassign char * to null

I'm a little bit confused regarding string memory usage in c++.
Is it good reassign *PChar to NULL second time? Will assigned first time to *PChar string memory be released?
char * fnc(int g)
{
...
}
char *PChar = NULL;
PChar=fnc(1);
if (PChar) { sprintf(s,"%s",PChar); } ;
*PChar = NULL;
PChar=fnc(2);
if (PChar) { sprintf(s,"%s",PChar); } ;
First things first. The following statement is not what you intend:
*PChar = NULL;
PChar=fnc(2);
You are NOT assigning null to the pointer, but putting value zero (0) to the first character of the said buffer. You might be willing to do:
PChar = NULL;
PChar=fnc(2);
As a good programming practice, yes you should assign a pointer to null after it is used (AND possibility memory-deallocated). But assigning a pointer to null will not free the memory - the pointer will not point to allocated memory, but to non-existent memory location. You need to call delete if it was allocated using new, or need to call free if allocated by malloc.
As for the given statement, the compiler would anyway remove the following statement, as the process of optimization:
// PChar = NULL;
PChar=fnc(2);
You need to be very careful while using pointers, and assignment to it with a statically allocated data or dynamically allocated buffer!
I would suggest declaring a buffer of the PChar type and pass pointer to this buffer in a function call.
Good programming practice cals for passing also the allowed length of the buffer that should be checked in th function.
#define MAX_PCHAR_LEN 1024 // or constant const DWORD . . .
PChar PCharbuf[MAX_PCHAR_LEN] = {0}; // initialize array with 0s
//make a call
fnc (&PCharbuf, MAX_PCHAR_LEN, 2); // whatever 2 means
This way you do not have to worry about who allocates and who released memory, since release is automatic after PCharbuf goes out of scope.

Identifying memory leaks in C++

I've got the following bit of code, which I've narrowed down to be causing a memory leak (that is, in Task Manager, the Private Working Set of memory increases with the same repeated input string). I understand the concepts of heaps and stacks for memory, as well as the general rules for avoiding memory leaks, but something somewhere is still going wrong:
while(!quit){
char* thebuffer = new char[210];
//checked the function, it isn't creating the leak
int size = FuncToObtainInputTextFromApp(thebuffer); //stored in thebuffer
string bufferstring = thebuffer;
int startlog = bufferstring.find("$");
int endlog = bufferstring.find("&");
string str_text="";
str_text = bufferstring.substr(startlog,endlog-startlog+1);
String^ str_text_m = gcnew String(str_text_m.c_str());
//some work done
delete str_text_m;
delete [] thebuffer;
}
The only thing I can think of is it might be the creation of 'string str_text' since it never goes out of scope since it just reloops in the while? If so, how would I resolve that? Defining it outside the while loop wouldn't solve it since it'd also remain in scope then too. Any help would be greatly appreciated.
You should use scope-bound resource management (also known as RAII), it's good practice in any case. Never allocate memory manually, keep it in an automatically allocated class that will clean up the resource for you in the destructor.
You code might read:
while(!quit)
{
// completely safe, no leaks possible
std::vector<char> thebuffer(210);
int size = FuncToObtainInputTextFromApp(&thebuffer[0]);
// you never used size, this should be better
string bufferstring(thebuffer, size);
// find does not return an int, but a size_t
std::size_t startlog = bufferstring.find("$");
std::size_t endlog = bufferstring.find("&");
// why was this split across two lines?
// there's also no checks to ensure the above find
// calls worked, be careful
string str_text = bufferstring.substr(startlog, endlog - startlog + 1);
// why copy the string into a String? why not construct
// this directly?
String^ str_text_m = gcnew String(str_text_m.c_str());
// ...
// don't really need to do that, I think,
// it's garbage collected for a reason
// delete str_text_m;
}
The point is, you won't get memory leaks if you're ensured your resources are freed by themselves. Maybe the garbage collector is causing your leak detector to mis-fire.
On a side note, your code seems to have lots of unnecessary copying, you might want to rethink how many times you copy the string around. (For example, find "$" and "&" while it's in the vector, and just copy from there into str_text, no need for an intermediate copy.)
Are you #using std, so that str_text's type is std::string? Maybe you meant to write -
String^ str_text_m = gcnew String(str_text.c_str());
(and not gcnew String(str_text_m.c_str()) ) ?
Most importantly, allocating a String (or any object) with gcnew is declaring that you will not be delete'ing it explicitly - you leave it up to the garbage collector. Not sure what happens if you do delete it (technically it's not even a pointer. Definitely does not reference anything on the CRT heap, where new/delete have power).
You can probably safely comment str_text_m's deletion. You can expect gradual memory increase (where the gcnew's accumulate) and sudden decreases (where the garbage collection kicks in) in some intervals.
Even better, you can probably reuse str_text_m, along the lines of -
String^ str_text_m = gcnew String();
while(!quit){
...
str_text_m = String(str_text.c_str());
...
}
I know its recommended to set the freed variable to NULL after deleting it just to prevent any invalid memory reference. May help, may not.
delete [] thebuffer;
thebuffer = NULL; // Clear a to prevent using invalid memory reference
There is a tool called DevPartner which can catch all memory leaks at runtime. If you have the pdb for your application this will give you the line numbers in your application where all memory leak has been observed.
This is best used for really big applications.

Resources