views:

129

answers:

7

This code is compiling clean. But when I run this, it gives exception "Access violation writing location" at line 9.

void reverse(char *word)
{
int len = strlen(word);
len = len-1;
char * temp= word;
int i =0;
while (len >=0)
{
word[i] = temp[len];  //line9
++i;--len;
}
word[i] = '\0';
}
+4  A: 

Be careful: not all strings in a C++ program are writable. Even if your code is good it can still crash when someone calls it with a string literal.

compie
Um...if it's been passed into the function he quoted, it's not his problem. There's no `const` in the argument declaration.
T.J. Crowder
@T.J: it's his problem if he also wrote the calling code. Which is overwhelmingly likely. But this code can crash even without being passed a string literal, so who knows?
Steve Jessop
@Steve: Disagree that it's likely at all. Completely agree there are a bunch of other (and much more significant) issues with the code.
T.J. Crowder
@T.J: really? So who did write the calling code? My thought process is that the questioner clearly wrote this `reverse` function himself, so he probably wrote the harness to call it himself, too. Surely no teacher/tutorial would be so sneaky as to set an assignment where even if you implement the function correctly, it still crashes because the teacher-provided calling code is wrong. Or are C++ instructors more sadistic than I thought?
Steve Jessop
@Steve Jessop: this code can crash on a _read_ violation, but not a _write_ violation unless the input is unwritable.
John Knoeller
@John: fair point. I agree that (most likely) the cause of the write violation is that a string literal is being passed in. I disagree with T.J. that this isn't the questioner's problem, but I intended to concede to T.J that since the stated question is "what's wrong *with this function*", and there clearly are things wrong with this function, things that are wrong with the calling code are beyond our current certain knowledge...
Steve Jessop
+3  A: 

When len gets to 0, you access the location before the start of the string (temp[0-1]).

Donal Fellows
That's *one* problem. There are several others.
T.J. Crowder
Yeah, at many levels. The more I look at this, the more I think it is a "debug my homework" question.
Donal Fellows
That can't cause a _write_ crash, that would be a _read_ crash.
John Knoeller
+7  A: 

Have you stepped through this code in a debugger?

If not, what happens when i (increasing from 0) passes len (decreasing towards 0)?

Note that your two pointers word and temp have the same value - they are pointing to the same string.

Charles Bailey
Nail head? Meet hammer. Not once, not twice, but three times. Big +1
T.J. Crowder
Yes. I am running it in debugger. When I replace the target in the while loop(char *word) with another char array(lets say char dest[20]), the code is working fine. I am wondering why its not working when I am using the same char *word.
AKS
Step through the debugger with a test string that is "important ". That's the word _important_ followed by ten spaces. After nine iterations, what has happened?
Charles Bailey
A: 

Well, for one, when len == 0 len-1 will be a negative number. And that's pretty illegal. Second, it's quite possible that your pointer is pointing at an unreserved area of memory.

zdawg
+1  A: 

The function looks like it would not crash, but it won't work correctly and it will read from word[-1], which is not likely to cause a crash, but it is a problem. Your crashing problem is probably that you passed in a string literal that the compiler had put into a read-only data segment.

Something like this would crash on many operating systems.

char * word = "test";
reverse(word); // this will crash if "test" isn't in writable memory

There are also several problems with your algorithm. You have len = len-1 and later temp[len-1] which means that the last character will never be read, and when len==0, you will be reading from the first character before the word. Also, temp and word are both pointers, so they both point to the same memory, I think you meant to make a copy of word rather than just a copy of the pointer to word. You can make a copy of word with strdup. If you do that, and fix your off-by-one problem with len, then your function should work,

But that still won't fix the write crash, which is caused by code that you have not shown us.

Oh, and if you do use strdup be sure to call free to free temp before you leave the function.

John Knoeller
Making a copy with strdup in a function that takes a non-const parameter and returns `void` doesn't sound right to me. I think it's *supposed* to be an in-place reverse, it's just not quite right yet.
Steve Jessop
temp[len -1] is a typo. Sorry about that
AKS
@AKS: show us the code that calls this function please.
John Knoeller
@Steve Jessop: There's no need for temp at all with an inplace reverse, but there's so many problems here, its impossible to know.
John Knoeller
Agreed. When I read it, I thought "whoever wrote this code has seen string-mangling functions which increment pointers, started to copy that style, and then bottled it and gone for indexes instead". It didn't occur to me that the questioner thought he was taking a copy of the string, but now I see your point. At this level, though, I'd say that if you suggest calling `strdup`, suggest calling `free` too, because it's not going to occur to the student otherwise ;-)
Steve Jessop
+1  A: 

Try this:

void reverse(char *word)
{
  size_t len = strlen(word);
  size_t i;

  for (i = 0; i < len / 2; i++)
    {
      char temp = word[i];
      word[i] = word[len - i - 1];
      word[len - i - 1] = temp;
    }
}
Tuomas Pelkonen
A: 

If you called that function as followed:

reverse("this is a test");

then with at least one compiler will pass in a read only string due to backwards compatibility with C where you can pass string literals as non-const char*.

MSN