1

I can't understand why this code is throwing an unhandled "Access Violation" exception. It's a simple program that attempts to copy one char pointer string to another while skipping some characters (chars at index: 3,4,5)

#include <conio.h>
#include <iostream>
using namespace std;


void main()
{
char str[20];
char *str1 = "abcdeabcde", *str2 = "";
int i, dx = 0;

for(i=0; *(str1+i)!='\0'; i++)
    if(i<3 || i>5)
    {
        *(str2 + dx) = *(str1 + i);
        dx++;
    }
*(str2+dx) = '\0';
cout<<str2;

_getch();
}

Whereas the assignment using syntax *(str + i) works fine in the following function code (it's an implementation of getline)

int getstr(char *str, int n)
{
    char ch;
    int i = 0;
    for(i=0; i<n && (ch = _getch())!= '\r'; i++)
    {
        if(ch == '\b')
        {
            if(i == 0)
            {
                i = -1; continue;
            }
            else
            {
                cout<<"\b \b";
                i -= 2;
            }
        }
        else if(ch > 31 && ch < 127 && i<n-1)
        {
            cout<<ch;
            *(str + i) = ch;
        }
        else
        {
            cout<<"\a";
            i--;
        }
    }
    *(str + i) = '\0';
    return i+1;
}

So why does this work in the second case but not in first?

CodeH
  • 15
  • 2
  • `std::string newstr(oldstr); newstr.erase(3,3);` does the job if you're not prohibited from STL assets. – Jack Deeth Dec 01 '16 at 11:23
  • If you used a standard compliant compiler, it would have told you that `char *str1 = "abcdeabcde", *str2 = ""` is ill-formed. – eerorika Dec 01 '16 at 11:26

2 Answers2

3

So why does this work in the second case but not in first?

Because in the first case, these are literal strings char *str1 = "abcdeabcde", *str2 = ""; and you are not allowed to change the content of either str1 and str2

This is a well-known undefined behavior in C/C++. See this list: What are all the common undefined behaviours that a C++ programmer should know about?

in particular this line:

  • Attempting to modify a string literal or any other const object during its lifetime (UB)
Community
  • 1
  • 1
artm
  • 17,291
  • 6
  • 38
  • 54
2

Here lies your problem:

*(str2 + dx) = *(str1 + i);

str2 is a pointer to a string literal. You can read from str2 as long as you don't read past its NUL character, but you are not allowed to write in it, since the compiler might store the string literal in a specific and read-only section of your binary.

Here, you write to str2 past its end. This is a double undefined behaviour!

YSC
  • 38,212
  • 9
  • 96
  • 149