Access Violation in a simple C++ program
I wrote a simple C++ program that removes the duplicate spaces in a string. The function doing the work is RemoveDupSpaces:
char* RemoveDupSpaces(char *s) {
char *a = s; char *b = s;
while(*a != '\0') {
while(*a != ' ' && *a != '\0') *b++ = *a++;
// copy one space
if(*a == ' ') *b++ = *a++;
// ignore other spaces
while(*a == ' ') a++;
}
*b = '\0';
return s;
}
Main calls this simple function, passing it a string:
std::cout << RemoveDupSpaces(" this is a test string for removing duplicate spaces ");
When I execute the program, I get the following access violation:
Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00417928 ebx=7ffde000 ecx=00417928 edx=00342c20 esi=0012fe6c edi=0012fe60
eip=0041194a esp=0012fd7c ebp=0012fe60 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
So what’s going on? Let’s take a look at the stack:
0:000> kP
ChildEBP RetAddr
0012fe60 00414ada StringOperations!RemoveDupSpaces(
char * s = 0x00417928 " this is a test string for removing duplicate spaces ")+0x7a
0012ff68 00412bb8 StringOperations!wmain(
int argc = 1,
wchar_t ** argv = 0x00345a90)+0x3aa
0012ffb8 004129ff StringOperations!__tmainCRTStartup(void)+0x1a8
0012ffc0 7c817067 StringOperations!wmainCRTStartup(void)+0xf
0012fff0 00000000 kernel32!BaseProcessStart+0x23
Ok, no surprise here. I am in RemoveDupSpaces. We can take a look at the local variables:
0:000> dv -V
0012fe68 @ebp+0x08 s = 0x00417928 " this is a test string for removing duplicate spaces "
0012fe4c @ebp-0x14 b = 0x00417928 " this is a test string for removing duplicate spaces "
0012fe58 @ebp-0x08 a = 0x00417928 " this is a test string for removing duplicate spaces "
Why the access violation? Let’s take a look at the memory at the address 0x00417928.
0:000> !address 0x00417928
00400000 : 00417000 - 00003000
Type 01000000 MEM_IMAGE
Protect 00000002 PAGE_READONLY
State 00001000 MEM_COMMIT
Usage RegionUsageImage
FullPath StringOperations.exe
We are trying to write in a read only location. To understand the issue, we need to delve a little in C++ memory management. We have 4 major memory segments:
1. Global: global variables (scoped to the entire program), static variables, static class and namespace members. This segment is fixed in size.
2. Code (text): the compiled program. This part is read only.
3. Heap: dynamically allocated variables.
4. Stack: parameters, automatic and temporary variables.
If you want to read more, you can start here. So, our problem is that the string is allocated from a read only segment. A simple fix: dynamically allocate the string in main will solve the issue, because this will give me read-write address:
const char * const s = " this is a test string for removing duplicate spaces ";
char *p = new char[strlen(s) + 1];
strcpy_s(p, strlen(s) + 1, s);
std::cout << RemoveDupSpaces(p);
delete [] p;