Code snippet to follow.
I have a struct (example code has class, tried both, same effect) that will store a number of char *. I made a constructor for the class that initializes most of them to = ""; Upon attempting to modify that member of an instance of the class, strncpy et all report access denied. These functions even report access denied when i use them in the scope of internal struct/class member functions.
Its been my assumption that having a char * member of a struct/class was no big deal and nothing special (apart from being a pointer to a char, which required that it be initialized at some point before being used, and destroyed at certain times).
I appreciate it if someone could tell me where my assumptions have been wrong, and direct me to some literature that would clarify whats going on. I am currently compiling the code under vs2008 full edition.
I expect that someone who will run this code will get a runtime error about being denied access to a certain memory location.
I also expect that when I make a char * mystr that when I later say mystr = ""; that the memory is initialized for mystr to then be used.
I'd also like to think i'm not an idiot, but when I try to use the locals window to determine the precise in memory address of a certain variable, I can't seem to get the ide to tell me where the memory is at. I ahve to get lucky in the memory window. oh well.
help! Thanks in advance. I hate dealing with these stupid char * cuz I always mess them up somehow, and my assumptions about how they work are flawwed. I want to change this so that I command them like the tools they are, not them frustrate me.
Thanks again for your consideration. Josh
#include <stdio.h>
#include <string.h>
class mystruct {
public:
int A;
char* B;
char* C;
mystruct() {
A = 0xFE;
B = new char[32];
B = "";
C = "test";
}
void test(char *input) {
strncpy(B,input, strlen(input));
}
};
int main(char* argv[], int argc) {
mystruct work;
char wtf[32];
// work.A = 0xbb;
work.test("gotchabitch!");
// sprintf(wtf, "address of work is %x" , &work);
// strncpy(work.C,"gotchabitch!\0",strlen("gotchabitch!\0"));
strncpy(work.B,"gotchabitch!",strlen("gotchabitch!"));
printf("%d;%s;%s;", work.A, work.B, work.C);
return 0;
}
Response to all: Ok, I've learned that when you assign a string literal to a char * that you're really saying char * const B = "something". (isn't that different from const char * B = something, where the latter is aa pointer whose address can not change, as opposed to the former which is a pointer to memory that can't be changed?). Either way, this explains the error message that I got. Thank you all for that.
B = new char[32];
B = "";
You first assign the pointer returned by new
to B
, then you assign a pointer to the string literal ""
to B
, effectively overwriting the pointer returned by new
.
As Jonathan Leffler explains , string literals are read-only, so you encounter an error when you try to write to the string literal ( ""
) pointed-to by B
.
If you want to store the empty string in B
, you need to use a library function like strcpy()
(or preferably, a safer function, like snprintf()
). In this case, you could also just assign \\0
to B[0]
, since that's the same thing. In C and C++, you can't assign arrays (or C strings, which are just arrays of characters) using =
.
Ideally, you should just use std::string
instead of raw C strings; then you don't have to worry about this sort of thing.
The problem is that when you tried to do:
strncpy(work.C, "something", strlen(something));
you are copying over readonly data - which is not a good idea. That's because the pointer, C, points to a string literal; overwriting string literals is not allowed. Similar comments apply to B - but there you are also leaking memory.
The key point is the comment you made about 'run time' not 'compile time' error. It is not that the member is inaccessible; it is just not abusable when you've initialized it as you have.
The error is in the line:
C = "test";
in mystruct's constructor. "test"
is a pointer to read-only memory, it's not safe to use it to initialize a non-const pointer. The only reason the compiler doesn't enforce this is the huge amount of C code created before people cared about const-correctness, which ought to be declared const
but aren't.
B = "";
is likewise not type-safe.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.