Kill process and release memory in c++ - c++

I have a service that it creates a process and then frees its memory.
I use createprocess() function and then close handle of process and thread,
this is my code:
if (CreateProcessA(NULL,
zAppName,//{ pointer to command line string }
NULL, //{ pointer to process security attributes }
NULL, //{ pointer to thread security attributes }
TRUE, //{ handle inheritance flag }
0,
NULL, //{ pointer to new environment block }
NULL, //{ pointer to current directory name }
&StartupInfo, //{ pointer to STARTUPINFO }
&ProcessInfo))
{
WaitForSingleObject(ProcessInfo.hProcess,WaitMiliSec);
GetExitCodeProcess(ProcessInfo.hProcess, &Result);
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
CloseHandle(hRead);
CloseHandle(hWrite);
return (Result);
}
But after closehandle() function, hProcess and hThread still have value!!!
and each time my service runs this code the memory increases and doesn't decrease!!!Is this a memory leak?
what should I do?

As the process is loaded into the memory following elements are loaded :
1.code
2.memory
2.PCB
4.Data etc.
When you close handles only some part of heap (assuming that you are using malloc to create handlers) is freed. So rest of elements still remains into the process stack. So you can't guarantee that memory is not freed.
yes hProcess and hThread might have some values that can create confusion. But these pointers hProcess and hThread will be called as "dangling pointers". So it is a good practice to assign a null value to the pointers after de-allocation.

Related

Why is CreateProcess API call causing memory access violations?

I have a function that is supposed to launch another process:
DWORD WINAPI StartCalc(LPVOID lpParam) {
STARTUPINFOW info;
PROCESS_INFORMATION processInfo;
std::wstring cmd = L"C:\\Windows\\System32\\calc.exe";
BOOL hR = CreateProcessW(NULL, (LPWSTR)cmd.c_str(), NULL, NULL, TRUE, 0, NULL, NULL,
&info, &processInfo);
if (hR == 0) {
DWORD errorMessageID = ::GetLastError();
printf("Error creating process\n");
return 1;
}
return 0;
}
I get an exception in ntdll.dll "Access violation reading location 0xFFFFFFFFFFFFFFFF". I know there are a few common mistakes that might cause this:
Inconsistent calling conventions. I am using __stdcall
Encoding issues. I storing strings as wide chars
The problem happens in both x64 and x86 builds
The problems happens when I try to create other Windows processes
What am i doing wrong?
EDIT: This actually isn't a problem with casting cmd.c_str() as a (LPWSTR), that part appears to be fine. I needed to initialize the STARTUPINFO struct: STARTUPINFO info = { 0 };
BOOL hR = CreateProcessW(NULL, (LPWSTR)cmd.c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo);
^^^^^
That's a cast. A great rule of thumb is "spot the cast, you spot the error".
It's true here. CreateProcessW must be passed a writable string. That means, no literal, and also no c_str() result.
From the documentation:
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
Pass a real non-const pointer, don't play hide-the-const. &cmd[0] should work, that's guaranteed to be a writable string. To be super-safe, increase your wstring capacity beyond just what you needed, because CreateProcessW is going to use it as a working buffer.

Is it safe to call CloseHandle (handle) who handle is NULL

Delete a NULL pointer is secure.
int* p = NULL;
delete p; // ok, secure
What ist about Handles?
HANDLE h = NULL;
CloseHandle(h); // allowed?
I am reading MSDN but still not sure. It say something about ERROR_INVALID_HANDLE but it is 6L, not NULL.
I come from a destructor of a class, which gives me a C6387 warning Error
if (m_hThread)
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread); // warninig C6387
m_hThread = NULL;
No. You may not call CloseHandle on a NULL handle. Look at the documentation for the argument. It says:
hObject [in] A valid handle to an open object.
NULL is not a handle to an open object.
The fact that you get C6387 is precisely because you are passing a "possibly-null" handle to CloseHandle.
You must write the code as:
if (m_hThread) {
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
}
(There is no point setting m_hThread to NULL after this - it is going to cease to exist in a very short while).

HeapFree() Possible Causes of Crash

typedef inside header file:
typedef struct tagMYSTRUCT {
wchar_t mystr[40] = { 0 };
DWORD threadId = NULL;
HANDLE threadHandle = NULL;
HWND receiverWnd = NULL;
} MYSTRUCT, *PMYSTRUCT;
Thread creation:
MYSTRUCT ats = *(PMYSTRUCT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYSTRUCT));
wcscpy(ats.mystr, L"hello");
ats.threadHandle = CreateThread(NULL, 0, MyThread, &ats, 0, &(ats.threadId));
This is thread which uses HeapFree() function. But it crashes. I believe this is bad practice but I want to know why. What is the logic behind and why HeapFree crashes program?
DWORD WINAPI MyThread(LPVOID lpParam) {
MYSTRUCT ActiveStruct = *(PMYSTRUCT)lpParam;
if (lpParam != NULL) {
std::cout << "1" << std::endl; // Gets printed.
HeapFree(GetProcessHeap(), NULL, lpParam);
std::cout << "2" << std::endl; // Crashes before this line.
}
...
}
You've obviously come from another language that blends the concepts of pointers and references differently than C++. Your usage is wildly inappropriate in C++. You have complicated things further by using non-standard functions (HeapAlloc() which is windows specific, not C++, etc) to manage memory.
If you are going to use HeapAlloc() (which is non-standard C++, being windows specific) or any standard function that dynamically allocates memory, the result needs to be stored in a pointer.
MYSTRUCT ats = *(PMYSTRUCT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYSTRUCT));
wcscpy(ats.mystr, L"hello");
ats.threadHandle = CreateThread(NULL, 0, MyThread, &ats, 0, &(ats.threadId));
What this does is convert the pointer returned by HeapAlloc() into a pointer to MYSTRUCT, dereferences that pointer which interprets that memory location as the value of a MYSTRUCT, and copies that value into ats.
At the least this is a memory leak - the memory allocated by HeapAlloc() is lost (never used again, it's address not stored anywhere), and you are passing the address of ats to the thread function.
There is therefore NO RELATIONSHIP between the memory allocated by HeapAlloc() and the address passed to the thread function.
Even worse is the thread function itself, which I've simplified here
DWORD WINAPI MyThread(LPVOID lpParam)
{
MYSTRUCT ActiveStruct = *(PMYSTRUCT)lpParam;
if (lpParam != NULL)
{
std::cout << "1" << std::endl; // Gets printed.
HeapFree(GetProcessHeap(), NULL, lpParam);
std::cout << "2" << std::endl; // Crashes before this line.
}
}
lpParam is going to contain the address of ats from the function that was passed by the function creating the thread.
If the function creating the thread has returned (after all, threads run in parallel) then that ats will no longer exist. If that happens, lpParam will be a dangling pointer (the address of an object that no longer exists as far as your program is concerned).
ActiveStruct is now going to be a local object which contains a copy of the object at the address passed to the function. In other words, it is a local copy of ats allocated previously by the func. If that ats has ceased to exist, and the address passed is dangling, the simple act of creating ActiveStruct causes undefined behaviour.
Even worse, lpParam is the address of (what was) ats. If ats still exists (i.e. the function which created the thread hasn't returned), it was not created on the heap, so should not be released using HeapFree(). If it no longer exists, then it shouldn't be passed to HeapFree() either. Either way, HeapFree() is being asked to release memory that was not allocated using HeapAlloc(). That will be virtually guaranteed to cause a runtime error.
At minimum, you need to change the code which creates the thread to
MYSTRUCT *ats = (PMYSTRUCT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYSTRUCT)); // note changed position of *
wcscpy(ats->mystr, L"hello"); // note usage of ats as a pointer
DWORD threadID; // we need these since ats is being released by the thread function
HANDLE threadHandle; // it is not a good idea for CreateThread() to use them
threadHandle = CreateThread(NULL, 0, MyThread, ats, 0, &(threadId)); // changes since ats is now a pointer
and the thread function to
DWORD WINAPI MyThread(LPVOID lpParam)
{
MYSTRUCT *ActiveStruct = (PMYSTRUCT)lpParam; // this is now a pointer
if (lpParam != NULL)
{
std::cout << "1" << std::endl; // Gets printed.
HeapFree(GetProcessHeap(), NULL, lpParam);
std::cout << "2" << std::endl; // Crashes before this line.
}
}
Since you are making fundamentally wrong assumptions about the C++ memory model, I would assume other things (which you haven't shown) are wrong in your code. But this should get you started.
You are getting in something of a mess over this. You are passing the address of a stack allocated structure which you do not intend to do. I think it's clear that you intend to pass the address a heap allocated structure. When you try to deallocate that structure, calling HeapFree, you encounter a runtime error because you passed to HeapFree the address of memory not allocated by HeapAlloc.
I'll show you how it is done using new and delete rather than HeapAlloc and HeapFree. There's really no need to use HeapAlloc here. Use the standard C++ memory allocator.
MYSTRUCT *pats = new MYSTRUCT(); // zero initialise
wcscpy(pats->mystr, L"hello");
DWORD threadId;
HANDLE threadHandle = CreateThread(NULL, 0, MyThread, pats, 0, &threadId);
....
DWORD WINAPI MyThread(LPVOID lpParam)
{
MYSTRUCT ActiveStruct = *(PMYSTRUCT)lpParam;
delete (PMYSTRUCT)lpParam;
// if you want the thread ID, call GetCurrentThreadId
// or if you want a thread handle call GetCurrentThread
}
Note that I did not attempt to store the thread handle and thread ID directly into the structure. That's because the structure could in theory be destroyed before the call to CreateThread returns. I'm using local variables instead. If your thread needs to find its ID, or obtain a handle to itself, there are API calls to do that.
1) you are not checking pointers before casting and dereferencing them
2) you are actually allocating MYSTRUCT on the stack and copy zeros from a heap-allocated buffer of MYSTRUCT size
3) your heap-allocated pointer leaks after copy assignment
4) you are passing pointer to stack-allocated MYSTRUCT instance to CreateThread which becomes invalid right after MYSTRUCT goes out of scope (which may happen at any time before new thread starts, while it works, or after it exits)
5) CreateThread and c++ runtime don't play well together
this is the corrected version if you insist on using HeapAlloc
PMYSTRUCT ats = (PMYSTRUCT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYSTRUCT));
if(ats == NULL)
return; // exit, throw do something
wcscpy(ats->mystr, L"hello");
CreateThread(NULL, 0, MyThread, ats, 0, &(ats.threadId));
HeapAlloc returns a pointer to the allocated memory, that is placed in a pointer. The pointer is then used to manipulate the allocated struct, finally this pointer is passed to the thread. And dont assign the result of createthread to something this is destroyed by the thread.

Windows: WaitForSingleObject crashes when thread returns 0

I am having a strange behavior: WaitForSingleObject seems to crash when I return 0 from my thread, but if I call "ExitThread(0)" then it does not.
void waitForThread(DWORD &threadId)
{
HANDLE hThread = OpenThread(SYNCHRONIZE,
FALSE,
threadId);
if (hThread == NULL) return;
WaitForSingleObject(hThread, INFINITE); // Crashes here (not even returning)
CloseHandle(hThread);
}
According to the documentation:
ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.
This does not make sense to me. I would think that "return 0" in my function with the signature:
DWORD WINAPI foo(LPVOID arg);
would be fine. For completeness, the thread is created using CreateThread, as such:
DWORD threadId;
HANDLE pth = CreateThread(NULL, // Default security attributes
0, // Default stack size
foo, // Thread name
arg, // Argument to thread
0, // Default creation flag
&threadId); // Returns thread ID
Does anyone know why the return statement would crash "WaitForSingleObject" please? I have put print statement before and after WaitForSingleObject, and one when the thread exists, and the behavior I see is: "Before WaitForSingleObject", "Thread finishes", Crash. Does anyone understand this behavior please?

Closing Handles/Stored Handles

I have some event handles and I add them to a list. I want to know if I can store these handles, close the local ones and still use the stored ones later.
Example:
std::map<std::string, HANDLE> Events;
DWORD OpenSingleEvent(std::string EventName, bool InheritHandle, DWORD dwDesiredAccess, DWORD dwMilliseconds)
{
Handle hEvent = OpenEvent(dwDesiredAccess, InheritHandle, EventName.c_str()); //Local Handle.
if (hEvent)
{
DeleteSingleEvent(EventName); //Delete the correct/old handle in the map.
Events.insert(EventName, hEvent); //Add this new handle to the map.
DWORD Result = WaitForSingleObject(hEvent, dwMilliseconds);
CloseHandle(hEvent); //Close THIS handle. Not the one in my Map.
return Result;
}
CloseHandle(hEvent); //Close this handle.
return WAIT_FAILED;
}
Will the above work? If not, is there another way to do this? It's for shared memory communication so I cannot duplicate handles since I only have the client PID not the Server's.
Also can someone explain what InheritHandle does? The function I use is OpenEvent and it has that parameter but I'm not sure what it does.
A HANDLE is simply a void *, it's a token which actually represents an object in kernel space. Calling CloseHandle actually deallocates the kernel object so the short answer to your question is no, you can't keep a list of them and then close all the local ones. All you'll have is a list of void* which don't represent anything.
What you can do is use DuplicateHandle which actually creates another kernel object on your behalf. However... why not just close the handles when you've finished with the entry in the list?