This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why does simple C code receive segmentation fault?
Why code snippet 2 doesn't behave like snippet 1?
//Code snippet 1
char pstr[] = "helloworld";
char *p = pstr;
p[2] = 'd';
//Code snippet 2
char *p = "helloworld";
p[2] = 'd'; //error: access violation
P.S Forgive my ignorance.
The first snippet creates an array of char and initializes its contents to "helloworld". Then you change its third element.
The second one simply creates a pointer to char that points to a string literal. Then you attempt to change the third character of that literal. String literals are not writable in code produced by many modern compilers.
EDIT:
GCC used to have an -fwritable-strings option that enabled string literals to be writable, since there is legacy code around that depends on this behaviour. That option was removed in the GCC 4.0 release series.
"helloworld" is an array of const char. There's a hole in the type system which allows you to point to it with a char*, because a lot of code exists which uses a char * to point to readonly data and this is safe.
But const_cast rules apply, you can't actually write to the const data even if you make a non-const pointer to it.
It would help if you could tell us in what way they're behaving differently.
But as a guess, I think your problem is that the second form has 'p' pointing to a string in read-only memory. Attempts to write through the pointer 'p' would result in a program failure.
I can tell you that the Gnu c++ compiler will warn you about this.
I'm guessing when you say "doesn't behave like" you mean one throws an illegal access exception (or something similar) while the other gives a compile time warning or error?
The answer is that in the first case, you're creating a pointer to your own memory, and copying the c9ontents into it. At that point the compiler forgets it used to be a pointer to static memory; the run time system, however, doesn't forget.
In the other case, the compiler "knows" p is a pointer to static memory, and so has the chance to say "whoa, dude, can't do that".
But this is a bit of a guess without knowing exactly what it does differently. it's also going to be compiler and implementation dependent.
Related
I am trying to change the properties of a file using C ++
what am I doing wrong ?
The code is completely taken
https://learn.microsoft.com/en-us/windows/win32/stg/writeread-sample
propspec.ulKind = PRSPEC_LPWSTR;
propspec.lpwstr = L"Property Name";// this line problem
propvarWrite.vt = VT_LPWSTR;
propvarWrite.pwszVal = L"Property Value"; // this line problem
As the error message tells already: String literals are of type const char[] or const wchar_t[] (depending on underlying type), and you cannot legally assign an array of const to a pointer to non-const (some compilers accept such code, though, just emitting a warning), solely the other way round is allowed.
Question is now, how to get out of that dilemma?
In general:
If you are 100% sure (really, not the very least doubt!) that the strings won't get modified, you could just cast the const away:
wchar_t* ptr = const_cast<wchar_t*>(L"...");
If you have the least doubt about (modifications of string literals are undefined behaviour!), then copy the literal into an array:
wchar_t value[] = L"...";
ptr = value;
At this point, you need to be sure that the called function won't take ownership of the string, though: Would it try to free the string? Would it store the pointer somewhere for later usage, such that the array pointed to must live longer than the scope of the calling function?
If so, you might need to use a global array or malloc memory to copy the string to...
In specific case:
If you peek into the documentation of read and write functions, you see that the structs in question are passed to const parameters. Well, actually, that will make the pointer constant, not the data pointed to, still it looks pretty much safe to assume that the strings won't get modified (if need be, copied to somewhere – well, written to some file), so you actually should be fine with the const_cast option.
Side note: The example doesn't free the strings read back again; pretty interesting now the question for ownership (who will free them again)? Unfortunately, the documentation is not precise about...
This question already has answers here:
Is a string literal in С++ created in static memory?
(4 answers)
Closed 6 years ago.
I'm trying to understand how const char * foo = "hello"; works under the hood. I interpret it as a string is created, and then a pointer points to it in memory.
So, does this line of code:
"hello";
take any memory?
"hello";
This does not take any memory because any modern compiler would optimize this away since it literally does nothing. If it was something more like:
const char* foo = "hello";
As you stated in your question, foo would be a char* to a static string that is baked into the program executable. Therefore the only run-time memory is the pointer to that string location.
Interesting question.
a string literal must take space in the static storage (the "data segment"), so yes, that string literal does take a place somewhere in the process memory.
but a good optimize will recognize that this literal is not reference nowhere, and will probably remove that string away. so I highly doubt that a program compiled with optimization on will retain that string.
If you simply execute "hello"; as an expression, almost any compiler will (probably even with optimization disabled) optimize it away to nothing.
That doesn't necessarily relate well to your starting point though. Given:
const char * foo = "hello";
You have another issue to consider: is that at namespace scope (i.e., outside any function)? If it's at global scope, the compiler probably can't optimize it away, even if it's not used. The problem is pretty simple: if it's outside any function, then some other source file could contain something like extern char const *foo;, and by doing so get access to foo, even though it's not used in the current file. Since the compiler only looks at one source file at a time, it has no way of detecting such a situation.
Depending on how smart it is, the linker (which does look at all the object files at once) may be able to detect that foo is never used, and based on that it could optimize it away.
If this definition is inside a function, then the compiler can detect whether it's used based solely on the content of that function, so we're back to a situation where it can be optimized away much more dependably.
I suggest looking into this link: http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/
foo points to a location on the stack in your case. So, yes, it takes up memory.
Edit: Sorry misread your code. You aren't assigning "hello" to anything.
So in your case, no.
Memory addresses are often displayed in hex formate like 0x7ffff3a9ae94. Why we can't directly assign these values to pointers?
int *ptr=7ffff3a9ae94;
A "similar" behavior was shown when i tried this.(This might be a separate question itself)
int i=0;
*ptr=&i;
&i=ptr;
Both cases show syntax errors on g++ 4.7.2 which, i assume means its a language restriction.
Why this restriction is implemented in C++?
Or is this some kind of OS limitation?
Note: This question have similar title but it doesn't provide me answer to my question.
there is no such rule , this :
int *ptr=(int*)0x7ffff3a9ae94;
compiles fine.
although it's a bad thing to to.
intresting fact : the idea that you can convert pointer to integer and vice versa is one of the biggest blocks when talking about garbage collector in C++ in general. you can (althoug it's stupid) to serialize the memory address in some external buffer, then re-assign it to some pointer. the GC may think it can delete the variable because nowone else points at it - while the pointer is still "valid" and will be dereference somewhere in the future
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C: How come an array's address is equal to its value?
I recently found code in my project that calls memcpy with the address of array name
int a[10];
memcpy(&a, &b ,sizeof(a));
Surprisingly (to me) it seems to work.
Should I change it to memcpy(a,b,sizeof(a)); ?
Is it allowed by the C++ spec?
Can anyone point me to resource about this behavior? Are there any pitfalls?
I also checked
assert((void*)&a == (void*)a);
and &a indeed is the same as a (besides it's type).
I verified this behavior in VS2005, VS2008 and VS2010.
&a is the address of the array; a can be implicitly converted to the address of the first element. Both have the same address, and so both will give the same value when converted to void*.
Are there any pitfalls?
memcpy is not typesafe, so it's quite easy to write code that compiles but behaves badly; for example, if a were a pointer rather than an array, then sizeof a would compile but give the wrong value. C++'s typesafe templates can protect against that:
std::copy(b, std::end(b), a); // will only compile if `b` has a known end.
The name of an array evaluates to the address of the beginning of the array, so the two have identical meaning. See How come an array's address is equal to its value in C? (it's a C question but the same holds for C++).
Like you say, it doesn't matter.
When passed as a parameter, the name of the array will "decay" into a pointer to its first element.
Yes, the address of an array is the same as the address of its first element.
So there's no need to change the memcpy call. Unless you're afraid that the definition of the array might change to a pointer later (like int* a = new int[10];).
Of course, if you're going to make changes to the program anyway, it might be best to dispense with the whole memcpy and use real C++ instead.
I'm trying to do some classic C development in Visual C++ 2008 that will modify the characters of a string like so:
void ModifyString(char *input)
{
// Change first character to 'a'
*input = 'a';
}
I'm getting a unhandled exception when I try to change a character. It seems like I could do this in Visual Studio 6 or using gcc, but maybe I'm just forgetting something. Does Visual Studio somehow pass char* by value (managing memory). If so, how do I turn this off?
You're probably passing a string literal somewhere:
ModifyString("oops"); // ERROR!
C and C++ allow you to implicitly cast from string literals (which have type const char[]) to char*, but such usage is deprecated. String constants are allowed to be allocated in read-only memory (and they usually are), so if you attempt to modify them, you'll get an access violation (aka segmentation fault or bus error). If the compiler doesn't put string constants in read-only memory, the program will still work, but it is undefined behavior.
The correct way to do this is to copy the string into a writeable buffer:
// one way:
char mystring[] = "test";
ModifyString(mystring); // ok
// another way:
char mystring[64]; // make sure this is big enough!!
strcpy(mystring, "test");
ModifyString(mystring); // ok
Is the input a string literal? That's probably the problem. Otherwise you'll need to post more code, as the pointer has somehow ended up pointing at a readonly location in memory.
It's impossible to answer this question without seeing how ModifyString is called. The function itself is correct assuming it's contract is to be passed a non-NULL value.
However it's possible for the call site to fail by doing any number of things
Passing NULL
Passing const char by means of an evil cast
I can't say exactly why this doesn't work, but the problem is in your code, not Visual Studio. For some reason, you are passing an invalid pointer to the function. It is either a null pointer, or it points to some address you don't have read access to.
If you post some more of the code (where is the function called from, and how is it called?), we may be able to point out the exact problem.
The reason it worked in GCC or VC6 is quite simply that it is undefined behavior. The C++ standard doesn't say that "this should work", or "this should cause a crash". Anything can happen if you write to memory you don't have access to. And depending on the compiler, and the system you're running the application on, the address you end up accessing will vary. By sheer luck, you hit an address that caused an access violation when compiled with VC2008. Under GCC and VC6, you weren't as lucky, and got code which appeared to work, and simply wrote to some garbage address.