Click here to Skip to main content
15,886,782 members
Articles / Programming Languages / VC++
Tip/Trick

Allocating Memory in C/C++: How to Avoid Memory Mismatched Allocation/Deallocation Issues Detected by Intel® Inspector XE for Visual Studio 2015

Rate me:
Please Sign up or sign in to vote.
5.00/5 (11 votes)
1 May 2017CPOL3 min read 17.5K   81   8   4
This tip/trick introduces the basic ideas on how to avoid memory mismatched allocation/deallocation issues detected by Intel® Inspector XE for Visual Studio 2015

Introduction

While using Intel® Inspector XE in Visual Studio 2015 to detect memory leaks and stack manipulation issues in your code written in C/C++, you’ve might encountered that Intel® Inspector XE detects mismatched allocation/deallocation issues even though you properly deallocate each buffer after it has been previously allocated. In this article, we’ll discuss about how to properly deallocate memory buffers being allocated to survive memory mismatched allocation/deallocation issues detected by Intel® Inspector XE.

Memory Mismatched Allocation/Deallocation Issues

Suppose you have the following code that allocates a buffer in memory to store an array of N objects of specific type DATA and assigns address of buffer in memory to the pointer variable data:

C++
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

typedef struct tagData
{
 char* string;
} DATA, NEAR *PDATA, FAR* LPDATA;

const size_t N = 10;

int main()
{
 int count = 10;
 while (--count >= 0)
 {
  LPDATA data = (LPDATA)malloc(sizeof(DATA) * N);
  memset((void*)&data[0], 0x00, sizeof(DATA) * N);

  const size_t length = 1024;
  for (size_t index = 0; index < N; index++)
  {
   data[index].string = (char*)malloc(length);
   sprintf(data[index].string, "string: %zu", index);
  }

  // Do some work at here

  for (size_t index = 0; index < N; index++)
   free(data[index].string);

  free(data);
 }

    return 0;
}

This is typically done by calling one of those C memory allocation functions such as calloc, malloc, realloc, as well as using new[] and delete[] operators in C++. Then, we’re iterating through the array of objects data and for each object we’re allocating process memory to store a character buffer string of size length using those memory allocation functions. In this case, we’re iteratively assigning the address of buffer being allocated to the pointer variable string of each particular object data[index].

Since those memory buffers have been allocated, we can do some work using the buffers being allocated. Finally, according to the best programming practices, to avoid memory leaks, we need to smartly deallocate specific buffers at the end of the code execution. To do this, we iterate through the array of objects, and for each particular object we deallocate memory used to store a string buffer by using C function free(data[index].string) or delete[] data[index].string operator in C++. After that, we deallocate buffer used to store an array of objects data using the same free(data) function.

Normally, by executing the following code listed above, we will see that it obviously can be successfully executed providing the correct results with no memory leaks or other issues at the end of its execution. However, by using Intel® Inspector XE to detect and analyze memory leaks or other issues that might persist during the code execution, we might encounter that the following code suddenly incurs a series of mismatched allocation/deallocation problems. We purposely repeat the process of memory allocation/deallocation to create workload on the CPU so that the following problems are easily detected by Intel® Inspector XE. Those problems basically occur when running the following code under Windows kernel:

Image 1

The main reason why those problems might be incurred by this code and thus detected by the Intel® Inspector XE is that calling the either free(data[index].string) function or free(data) does not actually deallocate the buffers when the following code is run under Windows kernel. Calling of these functions is equivalent to assigning the null-pointer to the specific pointer variables such as (data = nullptr). In turn, the memory being previously allocated at the beginning of code execution is automatically redistributed by the Windows kernel among other running processes. That’s actually why, Intel® Inspector suddenly detects those issues being discussed in this article.

Workaround

As a workaround to the problem being discussed, we have to use ::VirtualAllocEx(...) and ::VirtualFreeEx(...) WinAPI-functions to properly allocate/deallocate memory buffers. Also, to make sure, that we’re actually deallocating memory that was previously allocated, we have to perform a check if the value of address assigned to a pointer variable is not equal to nullptr. If so, perform deallocation, otherwise do nothing. Memory buffers allocation/deallocation is typically done as shown in the code example below:

C++
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <memory.h>

#include <Windows.h>

typedef struct tagData
{
 char* string;
} DATA, NEAR *PDATA, FAR* LPDATA;

const size_t N = 10;

int main()
{
 int count = 10;
 while (--count >= 0)
 {
  HANDLE hProcHandle = ::GetCurrentProcess();

  LPDATA data = (LPDATA)::VirtualAllocEx(hProcHandle, NULL, \
   sizeof(DATA) * N, MEM_COMMIT, PAGE_READWRITE);
  ::ZeroMemory((void*)&data[0], sizeof(DATA) * N);

  const size_t length = 1024;
  for (size_t index = 0; index < N; index++)
  {
   data[index].string = (char*)::VirtualAllocEx(hProcHandle, NULL, \
    length, MEM_COMMIT, PAGE_READWRITE);
   sprintf(data[index].string, "string: %zu", index);
  }

  // Do some work here

  for (size_t index = 0; index < N; index++)
   if (data[index].string != NULL)
    ::VirtualFreeEx(hProcHandle, data[index].string, length, MEM_RELEASE);

  if (data != NULL)
   ::VirtualFreeEx(hProcHandle, data, sizeof(DATA) * N, MEM_RELEASE);
 }

    return 0;
}

In this case, unlike using malloc(…) and free(…) functions, ::VirtualAllocEx(...) and ::VirtualFreeEx(…) WinAPI - functions allocate/deallocate specific buffers in Windows kernel virtual memory address space. Since that, Intel® Inspector XE no longer detects any problems such as the memory allocation/deallocation mismatch. The detailed description of those functions that perform virtual memory management can be found here.

History

  • May 1, 2017 - The first revision of this tip/trick was published

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) EpsilonDev
Ukraine Ukraine
I’m software developer, system analyst and network engineer, with over 20 years experience, graduated from L’viv State Polytechnic University and earned my computer science and information technology master’s degree in January 2004. My professional career began as a financial and accounting software developer in EpsilonDev company, located at L’viv, Ukraine. My favorite programming languages - C/C++, C#.NET, Java, ASP.NET, Node.js/JavaScript, PHP, Perl, Python, SQL, HTML5, etc. While developing applications, I basically use various of IDE’s and development tools, including Microsoft Visual Studio/Code, Eclipse IDE for Linux, IntelliJ/IDEA for writing code in Java. My professional interests basically include data processing and analysis algorithms, artificial intelligence and data mining, system analysis, modern high-performance computing (HPC), development of client-server web-applications using various of libraries, frameworks and tools. I’m also interested in cloud-computing, system security audit, IoT, networking architecture design, hardware engineering, technical writing, etc. Besides of software development, I also admire to write and compose technical articles, walkthroughs and reviews about the new IT- technological trends and industrial content. I published my first article at CodeProject in June 2015.

Comments and Discussions

 
GeneralMy vote of 5 Pin
eslipak1-May-17 8:24
professionaleslipak1-May-17 8:24 
QuestionC++ Memory Allocation/Deallocation and Thread Safety Pin
Jon Summers1-May-17 3:03
Jon Summers1-May-17 3:03 
  1. First, why use C-style memory allocation in an article about C++? Does the use of new and delete affect your reasoning?
  2. Second, your discussion ignores the smart pointers introduced several years ago by Boost and which are now part of C++ 11 and later. It would be useful if you could comment on std::shared_ptr and its relevance to thread safety.

Regards, Jon Summers

AnswerRe: C++ Memory Allocation/Deallocation and Thread Safety Pin
Arthur V. Ratz1-May-17 3:37
professionalArthur V. Ratz1-May-17 3:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.