![]() |
VOOZH | about |
In C and C++, understanding how memory is managed is very important. Efficient memory management ensures that programs run smoothly without any leaks and crashes. However, manual memory management also introduces the potential for complex bugs such as using uninitialized memory or accessing memory after it has been freed. etc. In this article, we will learn how to handle these issues by initializing the memory blocks to specific patterns like 0xCD, 0xDD, etc.
To handle various memory management issues many compilers and runtime environments provide a variety of techniques during the development and debugging phases. One of those techniques is initializing memory blocks to specific patterns such as 0xCD, 0xDD, etc., and others when using memory management functions like , , and .
Now let's understand about each pattern and when and why the compiler will initialize memory to it:
Pattern Code | Cause | Description |
|---|---|---|
0xCD | This pattern is used to initialize the memory that is allocated using malloc or a new keyword in debug mode | It helps in identifying attempts to use memory before it has been explicitly assigned a value. Accessing uninitialized memory can lead to unpredictable behavior and bugs. By initializing it with a recognizable pattern (0xCD) debugger can easily detect such attempts. |
0xDD | This pattern is used to overwrite memory that has been freed using free or delete in debug mode | It helps to catch attempts to access memory that is no longer valid. Writing to or reading from freed memory can corrupt data and cause program crashes. By filling the freed memory with 0xDD, the debugger can easily detect such access attempts. |
0xAB | This pattern is not that much common but it can be used to represent memory that is intentionally left uninitialized. | It can be helpful for differentiating between truly uninitialized memory and memory filled with 0xCD Which indicate a bug where initialization was not performed. |
0xED | This pattern is not that much common and it is more compiler specific. It is used to indicate memory that has been explicitely set to zero. | Some debuggers and compiler use this pattern to differentiate between uninitialized memory and intentioanlly zeroed memory. |
0xCC | This pattern is used by some compilers to represent uninitialized memory or memory that is being deliberately overwritten with a specific value. | Debuggers uses |
Note: These patterns are compiler and OS specific. The given patterns are of MS CRT
The following program illustrates how the compiler will initialize memory to various pattern codes on using malloc/free/new/delete in C++:
Output
Contents of the uninitialized memory (should be 0xCD in debug mode):
Memory[0] = 0xCD
Memory[1] = 0xCD
Memory[2] = 0xCD
Memory[3] = 0xCD
Memory[4] = 0xCD
Memory[5] = 0xCD
Memory[6] = 0xCD
Memory[7] = 0xCD
Memory[8] = 0xCD
Memory[9] = 0xCD
Contents of the deallocated memory (should be 0xDD in debug mode):
Memory[0] = 0xDD
Memory[1] = 0xDD
Memory[2] = 0xDD
Memory[3] = 0xDD
Memory[4] = 0xDD
Memory[5] = 0xDD
Memory[6] = 0xDD
Memory[7] = 0xDD
Memory[8] = 0xDD
Memory[9] = 0xDD
Note: To execute the above code and get the required output we must execute it in debug mode in our code editors. To execute the above code in debug mode in Microsoft VS Code follow the below steps:
Create a file named main.cpp and copy the above code inside it.
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "g++",
"args": [
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$gcc"],
"detail": "Generated task by Debugger."
}
]
}
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}/${fileBasenameNoExtension}",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "build",
"miDebuggerPath": "/usr/bin/gdb",
"logging": {
"moduleLoad": false,
"trace": false,
"engineLogging": false,
"programOutput": true,
"exceptions": false
}
}
]
}
To build the project, press Ctrl + Shift +B in VS Code
To start debugging, press F5 in you VS Code and you will be able to see the following output on your terminal:
Following are some of the benefits for memory pattern initialization: