tags:

views:

84

answers:

3

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 a a 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.

+1  A: 
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.

James McNellis
+1  A: 

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.

Jonathan Leffler
+1  A: 

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.

Ben Voigt