Access Violation when assigning specific char to position in local CString

I've been toying around with a DirectX wrapper I got as part of a programming class I'm taking, and me and my roommates have been working on our own little side project to create a simple 8-bit style RPG using it. At the moment, I'm trying to create a tooltip method to allow me to pass a CString to it and print text based on the current mouse position, and this is what I was working with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
///Tooltip method.
#include <string.h>
#include "darkGDK.h"

const unsigned short TT_LINE_LIMIT = 32;

/* Creates a tooltip at the current mouse position using CString
passed through "char info[]" */
void toolTip(char info[]) {
	// Incrementor:
	int pos = 0;
	// Locations of the last space/newline:
	int lastSpace = -1, lastNewline = 0;

	/* Search through the entire string, replacing spaces with newline 
	characters if it has been more than 32 characters since the last
	newline. */
	do {
		// Mark position if it is a space.
		if (info[pos] == ' ') lastSpace = pos;

		// Mark position if it is a newline.
		if (info[pos] == '\n') lastNewline = pos;

		/* Replaces last space with '\n' if TT_LINE_LIMIT has been
		exceeded. */
		if (pos-lastNewline >= TT_LINE_LIMIT && lastSpace != -1) {
			info[lastSpace] = '\n';
			lastNewline = lastSpace;
		}

		// Increment position.
		++pos;
	}	while (info[pos] != '\0');

	// Split string into tokens at newline characters.
	char* strPoint = strtok(info, "\n");
	int line = 0;
	while (strPoint != NULL) {
		/* If the mouse is on the left side of the screen, print the
		tooltip normally.  Otherwise, offset the tooltip 10 pixels per
		TT_LINELIMIT value. */
		if (dbMouseX() < dbScreenWidth() / 2) {
			dbText(dbMouseX(), dbMouseY()+line*20, strPoint);
		} else {
			dbText(dbMouseX() - TT_LINE_LIMIT * 10,
				dbMouseY()+line*20, strPoint);
		}
		strPoint = strtok(NULL, "\n");
		++line;
	}
	return;
}


The trouble I'm getting is that when I get to info[lastSpace] = '\n'; (line 28 in the above) the compiler breaks with the error message "Unhandled exception at 0x001254e2 in Pseudo 8-Bit RPG.exe: 0xC0000005: Access violation writing location 0x00297ea7."

As near as I can tell, c++ just isn't letting me assign characters to specific elements in the array. I tried defining a separate CString in the method, and it lets me assign specific elements of that, just not the array that was passed as an argument to the method.

I also tried using the pipe (|) symbol as a deliminator instead (the only reason I was using the newline character as the delimiter was so that it would be more intuitive when passing info to the tooltip with manual newlines in it) but I still get the same error. Is there a way for me to regain access to that array so I can assign characters directly to its elements? Or, failing that, a different way to let me split the argument after a certain character limit?
Last edited on
Are you calling the function like this?

toolTip("Some string");

If so, your problem is that you are passing a const char* to the function, not a char*. Due to compatibility reasons with C (or something) it is allowed, but if you try to modify it, you will get an error, like you see.

Is there any reason why you can't just use std::string?
The main reason I wasn't using std::string was because I vaguely remember it being very difficult to fudge "strtok" to play nice with the string class, so I figured vanilla CStrings would be the simplest approach. I just assumed that the function would create a local char* copy of info and that it would therefore not be a constant.

My second question, then, would be: Is there a way to convert the const char* into a char*? I tried defining a different char* and assigning "info" to it, but apparently that somehow converts the char* into a second const char*.

If not, then my third question is: How would I use std:string to accomplish what the method is intended to do, and still allow a const char* to be passed as the argument?

Or, question number 4:
Passing a const char* as the argument was really just to test to see if the method was working properly. Within the actual game itself, I cannot imagine a situation in which I will ever need to pass a const char* to the function, since most of the time it will be used for things like printing the stats and flavor text of an item being moused-over in the inventory, which would mean it would be getting it's argument in the form of a CString built using sprintf and various accessor calls. Would a better solution be to go without the capability to pass const char*s to the method altogether, since they probably won't ever be needed in the intended implementation? (I did this anyhow as a workaround for testing the method, by using a temp CString initialized with the tooltip message and passing that to the method, and the method itself is otherwise working exactly as intended.)

In any case, thank you for your help on this. I fully admit that I'm far from an "expert" on this sort of thing, but I'm working to fix that, and asking questions helps me get closer ;)
Last edited on
Ok, so I found a way to make it accept a string literal as an argument on my own; I ended up dynamically allocating a separate char*, using strcpy to dump the contents of the const char* into it, and operating on that instead. (Probably just as well; this way I won't have to worry about what happens if the method changes the elements of the array passed to it.) Right now, the tentative "final" version of the method looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <string.h>
#include "darkGDK.h"

const unsigned short TT_LINE_LIMIT = 32;

///Tooltip method.
/* Creates a tooltip at the current mouse position using CString
passed through "char szText[]" */
void toolTip(char szText[]) {
	// Determine the length of szText.
	unsigned short length = 0;
	while (szText[length] != '\0') ++length;

	/* Create a dynamic copy of szText to allow assignments in the 
	case of string literals being passed as arguments. */
	char* text;
	text = new char [length+1];
	strcpy(text, szText);

	// Incrementor:
	int pos = 0;
	// Locations of the last space/newline:
	int lastSpace = -1, lastNewline = 0;

	/* Search through the entire string, replacing spaces with newline 
	characters if it has been more than 32 characters since the last
	newline. */
	do {
		// Mark position if it is a space.
		if (text[pos] == ' ') lastSpace = pos;

		// Mark position if it is a newline.
		if (text[pos] == '\n') lastNewline = pos;

		/* Replaces last space with '\n' if TT_LINE_LIMIT has been
		exceeded. */
		if (pos-lastNewline >= TT_LINE_LIMIT && lastSpace != -1) {
			text[lastSpace] = '\n';
			lastNewline = lastSpace;
		}

		// Increment position.
		++pos;
	}	while (text[pos] != '\0');

	// Split string into tokens at newline characters.
	char* strPoint = strtok(text, "\n");
	int line = 0;
	while (strPoint != NULL) {
		/* If the mouse is on the left side of the screen, print the
		tooltip normally.  Otherwise, offset the tooltip 8 pixels per
		TT_LINE_LIMIT value. */
		if (dbMouseX() < dbScreenWidth() / 2) {
			dbText(dbMouseX() + 20, dbMouseY() + line * 20, strPoint);
		} else {
			dbText(dbMouseX() - TT_LINE_LIMIT * 8,
				dbMouseY() + line * 20, strPoint);
		}
		strPoint = strtok(NULL, "\n");
		++line;
	}

	// Always free dynamically allocated memory.
	delete text;

	return;
}


If anyone can find a more efficient way to do this I'll be grateful, but for now this suits my purposes.
Last edited on
Topic archived. No new replies allowed.