Udostępnij za pośrednictwem


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;