searching process memory - c++

I'm working on a C++/MFC program that's leaking memory. The memory allocation numbers are different on each run, so using _CrtSetBreakAlloc() won't help me locate the allocation.
The memory is definitely a CString:
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(141) : {28660}
normal block at 0x02353F98, 29 bytes long. Data: << N†X >
3C 4E 86 58 0C 00 00 00 0C 00 00 00 01 00 00 00
And the string mostly starts with the following sequence:
< N†X
I would d like to know if there's a way to search process memory (while execution is paused in debug mode) so I can search for this string, and possibly determine the allocation point in the code, or even the variable name?

Better use Visual Leak Detector

Related

Why do you need to recompile C/C++ for each OS? [duplicate]

This question already has answers here:
Why are "Executable files" operating system dependent?
(6 answers)
Closed 2 years ago.
This is more of a theoretical question than anything. I'm a Comp sci major with a huge interest in low level programming. I love finding out how things work under the hood. My specialization is compiler design.
Anyway, as I'm working on my first compiler, things are occurring to me that are kind of confusing.
When you write a program in C/C++, the traditional thing people know is, a compiler magically turns your C/C++ code into native code for that machine.
But something doesn't add up here. If I compile my C/C++ program targeting the x86 architecture, it would seem that the same program should run on any computer with the same architecture. But that doesn't happen. You need to recompile your code for OS X or Linux or Windows.(And yet again for 32-bit vs 64-bit)
I'm just wondering why this is the case? Don't we target the CPU architecture/instruction set when compiling a C/C++ program? And a Mac OS and a Windows Os can very much be running on the same exact architecture.
(I know Java and similar target a VM or CLR so those don't count)
If I took a best-shot answer at this, I'd say C/C++ must then compile to OS-specific instructions. But every source I read says the compiler targets the machine. So I'm very confused.
Don't we target the CPU architecture/instruction set when compiling a C/C++ program?
No, you don't.
I mean yes, you are compiling for a CPU instruction set. But that's not all compilation is.
Consider the simplest "Hello, world!" program. All it does is call printf, right? But there's no "printf" instruction set opcode. So... what exactly happens?
Well, that's part of the C standard library. Its printf function does some processing on the string and parameters, then... displays it. How does that happen? Well, it sends the string to standard out. OK... who controls that?
The operating system. And there's no "standard out" opcode either, so sending a string to standard out involves some form of OS call.
And OS calls are not standardized across operating systems. Pretty much every standard library function that does something you couldn't build on your own in C or C++ is going to talk to the OS to do at least some of its work.
malloc? Memory doesn't belong to you; it belongs to the OS, and you maybe are allowed to have some. scanf? Standard input doesn't belong to you; it belongs to the OS, and you can maybe read from it. And so on.
Your standard library is built from calls to OS routines. And those OS routines are non-portable, so your standard library implementation is non-portable. So your executable has these non-portable calls in it.
And on top of all of that, different OSs have different ideas of what an "executable" even looks like. An executable isn't just a bunch of opcodes, after all; where do you think all of those constant and pre-initialized static variables get stored? Different OSs have different ways of starting up an executable, and the structure of the executable is a part of that.
How do you allocate memory? There's no CPU instruction for allocating dynamic memory, you have to ask the OS for the memory. But what are the parameters? How do you invoke the OS?
How do you print output? How do you open a file? How do you set a timer? How do you display a UI? All of these things require requesting services from the OS, and different OSes provide different services with different calls necessary to request them.
If I compile my C/C++ program targeting the x86 architecture, it would seem that the same program should run on any computer with the same architecture.
It is very true, but there're a few nuances.
Let's consider several cases of programs that are, from C-language point of view, OS-independent.
Suppose all that your program does, from the very beginning, is stress-testing the CPU by doing lots of computations without any I/O.
The machine code could be exactly the same for all the OSes (provided they all run in the same CPU mode, e.g. x86 32-bit Protected Mode). You could even write it in assembly language directly, it wouldn't need to be adapted for each OS.
But each OS wants different headers for the binaries containing this code. E.g. Windows wants PE format, Linux needs ELF, macOS uses Mach-O format. For your simple program you could prepare the machine code as a separate file, and a bunch of headers for each OS's executable format. Then all you need to "recompile" would actually be to concatenate the header and the machine code and, possibly, add alignment "footer".
So, suppose you compiled your C code into machine code, which looks as follows:
offset: instruction disassembly
00: f7 e0 mul eax
02: eb fc jmp short 00
This is the simple stress-testing code, repeatedly doing multiplications of eax register by itself.
Now you want to make it run on 32-bit Linux and 32-bit Windows. You'll need two headers, here're examples (hex dump):
For Linux:
000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 >.ELF............<
000010 02 00 03 00 01 00 00 00 54 80 04 08 34 00 00 00 >........T...4...<
000020 00 00 00 00 00 00 00 00 34 00 20 00 01 00 28 00 >........4. ...(.<
000030 00 00 00 00 01 00 00 00 54 00 00 00 54 80 04 08 >........T...T...<
000040 54 80 04 08 04 00 00 00 04 00 00 00 05 00 00 00 >T...............<
000050 00 10 00 00 >....<
For Windows (* simply repeats previous line until the address below * is reached):
000000 4d 5a 80 00 01 00 00 00 04 00 10 00 ff ff 00 00 >MZ..............<
000010 40 01 00 00 00 00 00 00 40 00 00 00 00 00 00 00 >#.......#.......<
000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................<
000030 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 >................<
000040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 >........!..L.!Th<
000050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f >is program canno<
000060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 >t be run in DOS <
000070 6d 6f 64 65 2e 0d 0a 24 00 00 00 00 00 00 00 00 >mode...$........<
000080 50 45 00 00 4c 01 01 00 ee 71 b4 5e 00 00 00 00 >PE..L....q.^....<
000090 00 00 00 00 e0 00 0f 01 0b 01 01 47 00 02 00 00 >...........G....<
0000a0 00 02 00 00 00 00 00 00 00 10 00 00 00 10 00 00 >................<
0000b0 00 10 00 00 00 00 40 00 00 10 00 00 00 02 00 00 >......#.........<
0000c0 01 00 00 00 00 00 00 00 03 00 0a 00 00 00 00 00 >................<
0000d0 00 20 00 00 00 02 00 00 40 fb 00 00 03 00 00 00 >. ......#.......<
0000e0 00 10 00 00 00 10 00 00 00 00 01 00 00 00 00 00 >................<
0000f0 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 >................<
000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................<
*
000170 00 00 00 00 00 00 00 00 2e 66 6c 61 74 00 00 00 >.........flat...<
000180 04 00 00 00 00 10 00 00 00 02 00 00 00 02 00 00 >................<
000190 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 e0 >............`...<
0001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................<
*
000200
Now if you append your machine code to these headers and, for Windows, also append a bunch of null bytes to make file size 1024 bytes, you'll get valid executables that will run on the corresponding OS.
Suppose now that your program wants to terminate after doing some amount of calculations.
Now it has two options:
Crash—e.g. by execution of an invalid instruction (on x86 it could be UD2). This is easy, OS-independent, but not elegant.
Ask the OS to correctly terminate the process. At this point we need an OS-dependent mechanism to do this.
On x86 Linux it would be
xor ebx, ebx ; zero exit code
mov eax, 1 ; __NR_exit
int 0x80 ; do the system call (the easiest way)
On x86 Windows 7 it would be
; First call terminates all threads except caller thread, see for details:
; http://www.rohitab.com/discuss/topic/41523-windows-process-termination/
mov eax, 0x172 ; NtTerminateProcess_Wind7
mov edx, terminateParams
int 0x2e ; do the system call
; Second call terminates current process
mov eax, 0x172
mov edx, terminateParams
int 0x2e
terminateParams:
dd 0, 0 ; processHandle, exitStatus
Note that on other Windows version you'd need another system call number. The proper way to call NtTerminateProcess is via yet another nuance of OS-dependence: shared libraries.
Now your program wants to load some shared library to avoid reinventing some wheels.
OK, we've seen that our executable file formats are different. Suppose that we've taken this into account and prepared the import sections for the file targeting each of the target OS. There's still a problem: the way to call a function—the so called calling convention—for each OS is different.
E.g. suppose the C-language function your program needs to call returns a structure containing two int values. On Linux the caller would have to allocate some space (e.g. on the stack) and pass the pointer to it as the first parameter to the function being called, like so:
sub esp, 12 ; 4*2+alignment: stack must be 16-byte aligned
push esp ; right before the call instruction
call myFunc
On Windows you'd get the first int value of the structure in EAX, and the second in EDX, without passing any additional parameters to the function.
There are other nuances like different name mangling schemes (though these can differ between compilers even on the same OS), different data types (e.g. long double on MSVC vs long double on GCC) etc., but the above mentioned ones are the most important differences between the OSes from the point of view of the compiler and linker.
No, you are not just targeting a CPU. You are also targeting the OS. Let's say you need to print something to the terminal screen using cout. cout will eventually wind up calling an API function for the OS the program is running on. That call can, and will, be different for different operating systems, so that means you need to compile the program for each OS so it makes the correct OS calls.
The standard library and the C-runtime must interact with OS API's.
The executable formats for the different target OS's are different.
Different OS kernels can configure the hardware differently. Things like byte order, stack direction, register use conventions, and probably many other things can be physically different.
Strictly speaking, you don't need to
Program Loaders
You have wine, the WSL1 or darling, which all are loaders for the respective other OS' binary formats. These tools work so well because the machine is basically the same.
When you create an executable, the machine code for "5+3" is basically the same on all x86 based platforms, however there are differences, already mentioned by the other answers, like:
file format
API: eg. Functions exposed by the OS
ABI: Binary layout etc.
These differ. Now, eg. wine makes Linux understand the WinPE format, and then "simply" runs the machine code as a Linux process (no emulation!). It implements parts of the WinAPI and translates it for Linux. Actually, Windows does pretty much the same thing, as Windows programs do not talk to the Windows Kernel (NT) but the Win32 subsystem... which translates the WinAPI into the NT API. As such, wine is "basically" another WinAPI implementation based on the Linux API.
C in a VM
Also, you can actually compile C into something else than "bare" machine code, like LLVM Byte code or wasm. Projects like GraalVM make it even possible to run C in the Java Virtual Machine: Compile Once, Run Everywhere. There you target another API/ABI/File Format which was intended to be "portable" from the start.
So while the ISA makes up the whole language a CPU can understand, most programs don't only "depend" on the CPU ISA but need the OS to be made work. The toolchain must see to that
But you're right
Actually, you are rather close to being right, however. You actually could compile for Linux and Win32 with your compiler and perhaps even get the same result -- for a rather narrow definition of "compiler". But when you invoke the compiler like this:
c99 -o foo foo.c
You don't only compile (translate the C code to, eg., assembly) but you do this:
Run the C preprocessor
Run the "actual" C compiler frontend
Run the assembler
Run the linker
There might be more or less steps, but that's the usual pipeline. And step 2 is, again with a grain of salt, basically the same on every platform. However the preprocessor copies different header files into your compilation unit (step 1) and the linker works completely differently. The actual translation from one language (C) to another (ASM), that is what from a theoretical perspective a compiler does, is platform independent.
For a binary to work properly (or in some cases at all) there are a whole lot of ugly details that need to be consistent/correct including but probablly not limited to.
How the C source constructs like procedure calls, parameters, types etc are mapped onto architecture-specific contstructs like registers, memory locations, stack frames etc.
How the results of compilation are expressed in an executable file so that the binary loader can load them into the correct places in the virtual address space and/or perform "fixups" after they are loaded in an arbitary place.
How exactly the standard library is implemented, sometimes standard library functions are actual functions in a library, but often they are instead macros, inline functions or even compiler builtins that may rely on non-standard functions in the library.
Where the boundary between the OS and the application is considered to be, on unix-like systems the C standard library is considered a core platform library. On the other hand on windows the C standard library is considered to be something that the compiler provides and is either compiled into the application or shipped alongside it.
How are other libraries implemented? what names do they use? how are they loaded?
Differences in one or more of these things are why you can't just take a binary intended for one OS and load it normally on another.
Having said that it is possible to run code intended for one os on another. That is essentially what wine does. It has special translator libraries that translate windows API calls into calls that are available on Linux and a special binary loader that knows how to load both windows and Linux binaries.

Relative vs Physical addresses in C++

I recently started learning about memory management and I read about relative addresses and physical addresses, and a question appeared in my mind:
When I print a variable's address, is it showing the relative (virtual) address or the physical address in where the variable located in the memory?
And another question regarding memory management:
Why does this code produce the same stack pointer value for each run (from Shellcoder's Handbook, page 28)?
Does any program that I run produce this address?
// find_start.c
unsigned long find_start(void)
{
__asm__("movl %esp, %eax");
}
int main()
{
printf("0x%x\n",find_start());
}
If we compile this and run this a few times, we get:
shellcoders#debian:~/chapter_2$ ./find_start
0xbffffad8
shellcoders#debian:~/chapter_2$ ./find_start
0xbffffad8
shellcoders#debian:~/chapter_2$ ./find_start
0xbffffad8
shellcoders#debian:~/chapter_2$ ./find_start
0xbffffad8
I would appreciate if someone could clarify this topic to me.
When I print a variable's address, is it showing the relative ( virtual ) address or the physical address in where the variable located in the memory ?
The counterpart to a relative address is an absolute address. That has nothing to do with the distinction between virtual and physical addresses.
On most common modern operating systems, such as Windows, Linux and MacOS, unless you are writing a driver, you will never encounter physical addresses. These are handled internally by the operating system. You will only be working with virtual addresses.
Why does this code produces the same stack pointer value for each run ( from shellcoder's handbook , page 28) ?
On most modern operating systems, every process has its own virtual memory address space. The executable is loaded to its preferred base address in that virtual address space, if possible, otherwise it is loaded at another address (relocated). The preferred base address of an executable file is normally stored in its header. Depending on the operating system and CPU, the heap is probably created at a higher address, since the heap normally grows upward (towards higher addresses). Because the stack normally grows downward (towards lower addresses), it will likely be created below the load address of the executable and grow towards the address 0.
Since the preferred load address is the same every time you run the executable, it is likely that the virtual memory addresses are the same. However, this may change if address layout space randomization is used. Also, just because the virtual memory addresses are the same does not mean that the physical memory address are the same, too.
Does any program that I will run produce this address ?
Depending on your operating system, you can set the preferred base address in which your program is loaded into virtual memory in the linker settings. Many programs may still have the same base address as your program, probably because both programs were built using the same linker with default settings.
The virtual addresses are only per program? Let's say I have 2 programs: program1 and program2. Can program2 access program1's memory?
It is not possible for program2 to access program1's memory directly, because they have separate virtual memory address spaces. However, it is possible for one program to ask the operating system for permission to access another process's address space. The operating system will normally grant this permission, provided that the program has sufficient priviledges. On Windows, this is can be accomplished for example with the function WriteProcessMemory. Linux offers similar functionality by using ptrace and writing to /proc/[pid]/mem. See this link for further information.
You get virtual addresses. Your program never gets to see physical addresses. Ever.
can program2 access program1's memory ?
No, because you can don't have addresses that point to program1's memory. If you have virtual address 0xabcd1234 in the program1 process, and you try to read it from the program2 process, you get program2's 0xabcd1234 (or a crash if there is no such address in program2). It's not a permission check - it's not like the CPU goes to the memory and sees "oh, this is program1's memory, I shouldn't access it". It's program2's own memory space.
But yes, if you use "shared memory" to ask the OS to put the same physical memory in both processes.
And yes, if you use ptrace or /proc/<pid>/mem to ask the OS nicely to read from the other process's memory, and you have permission to do that, then it will do that.
why does this code produces the same stack pointer value for each run ( from shellcoder's handbook , page 28) ? does any program that I will run will produce this address ?
Apparently, that program always has that stack pointer value. Different programs might have different stack pointers. And if you put more local variables in main, or call find_start from a different function, you will get a different stack pointer value because there will be more data pushed on the stack.
Note: even if you run the program twice at the same time, the address will be the same, because they are virtual addresses, and every process has its own virtual address space. They will be different physical addresses but you don't see the physical addresses.
In stack overflow example in the book I mentioned, they overwrite the return address in the stack to an address of an exploit in the enviroment variables. how does it work ?
It all works within one process.
Only focusing on a small part of your question.
#include <stdio.h>
// find_start.c
unsigned long find_start(void)
{
__asm__("movl %esp, %eax");
}
unsigned long nest ( void )
{
return(find_start());
}
int main()
{
printf("0x%lx\n",find_start());
printf("0x%lx\n",nest());
}
gcc so.c -o so
./so
0x50e381a0
0x50e38190
There is no magic here. The virtual space allows for programs to be built the same. I don't need to know where my program is going to live, each program can be compiled for the same address space, when loaded and run the can see the same virtual address space because they are all mapped to separate/different physical address spaces.
readelf -a so
(don't but I prefer objdump)
objdump -D so
Disassembly of section .text:
0000000000000540 <_start>:
540: 31 ed xor %ebp,%ebp
542: 49 89 d1 mov %rdx,%r9
545: 5e pop %rsi
....
000000000000064a <find_start>:
64a: 55 push %rbp
64b: 48 89 e5 mov %rsp,%rbp
64e: 89 e0 mov %esp,%eax
650: 90 nop
651: 5d pop %rbp
652: c3 retq
0000000000000653 <nest>:
653: 55 push %rbp
654: 48 89 e5 mov %rsp,%rbp
657: e8 ee ff ff ff callq 64a <find_start>
65c: 5d pop %rbp
65d: c3 retq
000000000000065e <main>:
65e: 55 push %rbp
65f: 48 89 e5 mov %rsp,%rbp
662: e8 e3 ff ff ff callq 64a <find_start>
667: 48 89 c6 mov %rax,%rsi
66a: 48 8d 3d b3 00 00 00 lea 0xb3(%rip),%rdi # 724 <_IO_stdin_used+0x4>
671: b8 00 00 00 00 mov $0x0,%eax
676: e8 a5 fe ff ff callq 520 <printf#plt>
67b: e8 d3 ff ff ff callq 653 <nest>
So, two things or maybe more than two things. Our entry point _start is in ram at a low address. low virtual address. On this system with this compiler I would expect all/most programs to start in a similar place or the same or in some cases it may depend on what is in my program, but it should be somewhere low.
The stack pointer though, if you check above and now as I type stuff:
0x355d38d0
0x355d38c0
it has changed.
0x4ebf1760
0x4ebf1750
0x31423240
0x31423230
0xa63188d0
0xa63188c0
a few times within a few seconds. The stack is a relative thing not absolute so there is no real need to create a fixed address that is the same every time. Needs to be in a space that is related to this user/thread and virtual since it is going through the mmu for protection reasons. There is no reason for a virtual address to not equal the physical address. The kernel code/driver that manages the mmu for a platform is programmed to do it a certain way. You can have the address space for code start at 0x0000 for every program, and you might wish the address space for data to be the same, zero based. but for stack it doesn't matter. And on my machine, my os, this particular version this particular day it isn't consistent.
I originally thought your question was different depending on factors that are specific to your build, and settings. For a specific build a single call to find_start is going to be at a fixed relative address for the stack pointer each function that uses the stack will put it back the way it was found, assuming you can't change the compilation of the program while running the stack pointer for a single instance of the call the nesting will be the same the stack consumption by each function along the way will be the same.
I added another layer and by looking at the disassembly, main, nest and find_start all mess with the stack pointer (unoptimized) so that is why for these runs they are 0x10 apart. if I added/removed more code per function to change the stack usage in one or more of the functions then that delta could change.
But
gcc -O2 so.c -o so
objdump -D so > so.txt
./so
0x0
0x0
Disassembly of section .text:
0000000000000560 <main>:
560: 48 83 ec 08 sub $0x8,%rsp
564: 89 e0 mov %esp,%eax
566: 48 8d 35 e7 01 00 00 lea 0x1e7(%rip),%rsi # 754 <_IO_stdin_used+0x4>
56d: 31 d2 xor %edx,%edx
56f: bf 01 00 00 00 mov $0x1,%edi
574: 31 c0 xor %eax,%eax
576: e8 c5 ff ff ff callq 540 <__printf_chk#plt>
57b: 89 e0 mov %esp,%eax
57d: 48 8d 35 d0 01 00 00 lea 0x1d0(%rip),%rsi # 754 <_IO_stdin_used+0x4>
584: 31 d2 xor %edx,%edx
586: bf 01 00 00 00 mov $0x1,%edi
58b: 31 c0 xor %eax,%eax
58d: e8 ae ff ff ff callq 540 <__printf_chk#plt>
592: 31 c0 xor %eax,%eax
594: 48 83 c4 08 add $0x8,%rsp
598: c3 retq
The optimizer didn't recognize the return value for some reason.
unsigned long fun ( void )
{
return(0x12345678);
}
00000000000006b0 <fun>:
6b0: b8 78 56 34 12 mov $0x12345678,%eax
6b5: c3 retq
calling convention looks fine.
Put find_start in a separate file so the optimizer can't remove it
gcc -O2 so.c sp.c -o so
./so
0xb1192fc8
0xb1192fc8
./so
0x7aa979d8
0x7aa979d8
./so
0x485134c8
0x485134c8
./so
0xa8317c98
0xa8317c98
./so
0x2ba70b8
0x2ba70b8
Disassembly of section .text:
0000000000000560 <main>:
560: 48 83 ec 08 sub $0x8,%rsp
564: e8 67 01 00 00 callq 6d0 <find_start>
569: 48 8d 35 f4 01 00 00 lea 0x1f4(%rip),%rsi # 764 <_IO_stdin_used+0x4>
570: 48 89 c2 mov %rax,%rdx
573: bf 01 00 00 00 mov $0x1,%edi
578: 31 c0 xor %eax,%eax
57a: e8 c1 ff ff ff callq 540 <__printf_chk#plt>
57f: e8 4c 01 00 00 callq 6d0 <find_start>
584: 48 8d 35 d9 01 00 00 lea 0x1d9(%rip),%rsi # 764 <_IO_stdin_used+0x4>
58b: 48 89 c2 mov %rax,%rdx
58e: bf 01 00 00 00 mov $0x1,%edi
593: 31 c0 xor %eax,%eax
595: e8 a6 ff ff ff callq 540 <__printf_chk#plt>
I didn't let it inline those functions it can see nest so it inlined it removing the stack change that came with it. So now the value nested or not is the same.

Visual studio 2010 - data segment and stack memory are same

I figured out that a constant literal get's placed in the data segment of the program (from SO) and is read-only and hence the line " s[0] = 'a' " would cause an error, which actually did happen when I uncommented that line and ran. However when I looked into the memory window in MS VS, the variables are all placed together in memory. I am curious as to how they(compiler) enforce read-only access to 's'?
#include <iostream>
int main(void)
{
char *s = "1023";
char s_arr[] = "4237";
char *d = "5067";
char s_arr_1[] = "9999";
char *e = "6789";
printf("%c\n", s[0]);
// s[0] = 'a'; This line would error out since s should point to data segment of the program
printf("%s\n", s);
system ("pause");
}
0x002E54F4 31 30 32 33 00 00 00 00 34 32 33 37 00 00 00 00 1023....4237....
0x002E5504 35 30 36 37 00 00 00 00 39 39 39 39 00 00 00 00 5067....9999....
0x002E5514 36 37 38 39 00 00 00 00 25 63 0a 00 25 73 0a 00 6789....%c..%s..
0x002E5524 70 61 75 73 65 00 00 00 00 00 00 00 43 00 3a 00 pause.......C.:.
Edit 1:
Updating the value stored in s_arr (which should be placed in stack space) to make it clear that it is placed adjacent to the string constants.
Edit 2: Since I am seeing answers regarding ro/rw access based on pages,
Here address .. 0x...4f4 is rw 0x...4fc is ro and again 0x...504 is rw. How do they achieve this granularity? Also since the each page could be a minimum of 4kb, one could argue that the 0x4fb could be the last address of the previous ro page. But I have now added a few more variables to show that they are all placed contiguously in memory and the granularity is per every 8 bytes.
You could say, Since pages are at 4k level as you mentioned,
I don't know what made you think that your example shows modifiable memory next to non-modifiable memory. What "granularity" are you talking about? You memory dump does not show anything like that.
The string "4237" that you see in your memory dump is not your s_arr. That "4237" that you see there is a read-only string literal that was used as an initializer for the s_arr. That initializer was copied to s_arr. Meanwhile, the actual s_arr resides somewhere else (in the stack) and is perfectly modifiable. It contains "4237" as well (as its initial value), but that's a completely different "4237", which you don't see in your memory dump. Ask your program to print the address of s_arr and you will see that its is nowhere near the memory range that you dumped.
Again, your claim about "0x...4f4 is rw 0x...4fc is ro and again 0x...504 is rw" is completely incorrect. All these addresses are read-only. None of them are read-write. There no "granularity" there whatsoever.
Remember that a declaration like this
char s_arr[] = "4237";
is really equivalent to
const char *unnamed = "4237";
char s_arr[5];
memcpy(s_arr, unnamed, 5);
In your memory dump, you are looking at that unnamed address from my example above. That memory region is read-only. Your s_arr resides in completely different memory region, which is read-write.
Since 32 bit platforms were introduced, everything is placed into the same segment (This is not exactly so, but it is easier to think that this is so. There are minor caveats that require several pages to explain and they apply to operating system design).
The 32-bit address space is split into several pages. Intell allows to assign RO bits with the page granularity. Debuggers display only the 32-bit (64 bit) address that technically is an offset in the segment. It is fine to call this offset simply address. There will be no mistake in this.
Nevertheless linkers call different memory areas as segments. These segments have nothing to do with Intel memory segments. Linker segments (code, data, stack, etc) are loaded into diffrenet pages. These pages get different attributes (RO/RW, execution permission, etc).
The block of memory you are showing is area where string constants are stored (as you can see all 4 values are directly there one next to another). This area is marked as read-only. On Windows each 4Kb block of memory (page) can have its own attributes (read/write/execute), so even 2 adjascent locations can have different access flags.
The area where variables are is in different location (stack in your case). You can see it by checking value of &s immediate window (or watch window).

Exception handler

There is this code:
char text[] = "zim";
int x = 777;
If I look on stack where x and text are placed there output is:
09 03 00 00 7a 69 6d 00
Where:
09 03 00 00 = 0x309 = 777 <- int x = 777
7a 69 6d 00 = char text[] = "zim" (ASCII code)
There is now code with try..catch:
char text[] = "zim";
try{
int x = 777;
}
catch(int){
}
Stack:
09 03 00 00 **97 85 04 08** 7a 69 6d 00
Now between text and x is placed new 4 byte value. If I add another catch, then there will be something like:
09 03 00 00 **97 85 04 08** **xx xx xx xx** 7a 69 6d 00
and so on. I think that this is some value connected with exception handling and it is used during stack unwinding to find appropriate catch when exception is thrown in try block. However question is, what is exactly this 4-byte value (maybe some address to excception handler structure or some id)?
I use g++ 4.6 on 32 bit Linux machine.
AFAICT, that's a pointer to an "unwind table". Per the the Itanium ABI implementation suggestions, the process "[uses] an unwind table, [to] find information on how to handle exceptions that occur at that PC, and in particular, get the address of the personality routine for that address range. "
The idea behind unwind tables is that the data needed for stack unwinding is rarely used. Therefore, it's more efficient to put a pointer on the stack, and store the reast of the data in another page. In the best cases, that page can remain on disk and doesn't even need to be loaded in RAM. In comparison, C style error handling often ends up in the L1 cache because it's all inline.
Needless to say all this is platform-dependent and etc.
This may be an address. It may point to either a code section (some handler address), or data section (pointer to a build-time-generated structure with frame info), or the stack of the same thread (pointer to a run-time-generated table of frame info).
Or it may also be a garbage, left due to an alignment requirement, which EH may demand.
For instance on Win32/x86 there's no such a gap. For every function that uses exception handling (has either try/catch or __try/__except/__finally or objects with d'tors) - the compiler generates an EXCEPTION_RECORD structure that is allocated on the stack (by the function prolog code). Then, whenever something changes within the function (object is created/destroyed, try/catch block entered/exited) - the compiler adds an instruction that modifies this structure (more correctly - modifies its extension). But nothing more is allocated on the stack.

How to ignore false positive memory leaks from _CrtDumpMemoryLeaks?

It seems whenever there are static objects, _CrtDumpMemoryLeaks returns a false positive claiming it is leaking memory. I know this is because they do not get destroyed until after the main() (or WinMain) function. But is there any way of avoiding this? I use VS2008.
I found that if you tell it to check memory automatically after the program terminates, it allows all the static objects to be accounted for. I was using log4cxx and boost which do a lot of allocations in static blocks, this fixed my "false positives"...
Add the following line, instead of invoking _CrtDumpMemoryLeaks, somewhere in the beginning of main():
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
For more details on usage and macros, refer to MSDN article:
http://msdn.microsoft.com/en-us/library/5at7yxcs(v=vs.71).aspx
Not a direct solution, but in general I've found it worthwhile to move as much allocation as possible out of static initialization time. It generally leads to headaches (initialization order, de-initialization order etc).
If that proves too difficult you can call _CrtMemCheckpoint (http://msdn.microsoft.com/en-us/library/h3z85t43%28VS.80%29.aspx) at the start of main(), and _CrtMemDumpAllObjectsSince
at the end.
1) You said:
It seems whenever there are static objects, _CrtDumpMemoryLeaks returns a false positive claiming it is leaking memory.
I don't think this is correct. EDIT: Static objects are not created on heap. END EDIT: _CrtDumpMemoryLeaks only covers crt heap memory. Therefore these objects are not supposed to return false positives.
However, it is another thing if static variables are objects which themselves hold some heap memory (if for example they dynamically create member objects with operator new()).
2) Consider using _CRTDBG_LEAK_CHECK_DF in order to activate memory leak check at the end of program execution (this is described here: http://msdn.microsoft.com/en-us/library/d41t22sb(VS.80).aspx). I suppose then memory leak check is done even after termination of static variables.
Old question, but I have an answer. I am able to split the report in false positives and real memory leaks. In my main function, I initialize the memory debugging and generate a real memory leak at the really beginning of my application (never delete pcDynamicHeapStart):
int main()
{
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
char* pcDynamicHeapStart = new char[ 17u ];
strcpy_s( pcDynamicHeapStart, 17u, "DynamicHeapStart" );
...
After my application is finished, the report contains
Detected memory leaks!
Dumping objects ->
{15554} normal block at 0x00000000009CB7C0, 80 bytes long.
Data: < > DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD
{14006} normal block at 0x00000000009CB360, 17 bytes long.
Data: <DynamicHeapStart> 44 79 6E 61 6D 69 63 48 65 61 70 53 74 61 72 74
{13998} normal block at 0x00000000009BF4B0, 32 bytes long.
Data: < ^ > E0 5E 9B 00 00 00 00 00 F0 7F 9C 00 00 00 00 00
{13997} normal block at 0x00000000009CA4B0, 8 bytes long.
Data: < > 14 00 00 00 00 00 00 00
{13982} normal block at 0x00000000009CB7C0, 16 bytes long.
Data: < # > D0 DD D6 40 01 00 00 00 90 08 9C 00 00 00 00 00
...
Object dump complete.
Now look at line "Data: <DynamicHeapStart> 44 79 6E 61 6D 69 63 48 65 61 70 53 74 61 72 74".
All reportet leaks below are false positives, all above are real leaks.
False positives don't mean there is no leak (it could be a static linked library which allocates heap at startup and never frees it), but you cannot eliminate the leak and that's no problem at all.
Since I invented this approach, I never had leaking applications any more.
I provide this here and hope this helps other developers to get stable applications.
Can you take a snapshot of the currently allocated objects every time you want a list? If so, you could remove the initially allocated objects from the list when you are looking for leaks that occur in operation. In the past, I have used this to find incremental leaks.
Another solution might be to sort the leaks and only consider duplicates for the same line of code. This should rule out static variable leaks.
Jacob
Ach. If you are sure that _CrtDumpMemoryLeaks() is lying, then you are probably correct. Most alleged memory leaks that I see are down to incorect calls to _CrtDumpMemoryLeaks(). I agree entirely with the following; _CrtDumpMemoryLeaks() dumps all open handles. But your program probably already has open handles, so be sure to call _CrtDumpMemoryLeaks() only when all handles have been released. See http://www.scottleckie.com/2010/08/_crtdumpmemoryleaks-and-related-fun/ for more info.
I can recommend Visual Leak Detector (it's free) rather than using the stuff built into VS. My problem was using _CrtDumpMemoryLeaks with an open source library that created 990 lines of output, all false positives so far as I can tell, as well as some things coming from boost. VLD ignored these and correctly reported some leaks I added for testing, including in a native DLL called from C#.