I read this on wikipedia
int main(void)
{
char *s = "hello world";
*s = 'H';
}
When the program containing this code is compiled, the string "hello world" is placed in the section of the program executable file marked as read-only; when loaded, the operating system places it with other strings and constant data in a read-only segment of memory. When executed, a variable, s, is set to point to the string's location, and an attempt is made to write an H character through the variable into the memory, causing a segmentation fault**
i don't know why the string is placed in read only segment.please someone could explain this.
String literals are stored in read-only memory, that's just how it works. Your code uses a pointer initialized to point at the memory where a string literal is stored, and thus you can't validly modify that memory.
To get a string in modifiable memory, do this:
char s[] = "hello world";
then you're fine, since now you're just using the constant string to initialize a non-constant array.
There is a big difference between:
char * s = "Hello world";
and
char s[] = "Hello world";
In the first case, s is a pointer to something that you can't change. It's stored in read-only memory (typically, in the code section of your application).
In the latter case, you allocate an array in read-write memory (typically plain RAM), that you can modify.
When you do: char *s = "hello world"; then s is a pointer that points to a memory that is in the code part, so you can't change it.
When you do: char s[] = "Hello World"; then s is an array of chars
that are on the stack, so you can change it.
If you don't want the string to be changed during the program, it is better to do: char
const *s = ....;. Then, when you try to change the string, your program will not crash with segmentation fault, it will arise a compiler error (which is much better).
first have a good understanding of pointers, I will give u a short demo:
First let us analyze your code line by line. Lets start from main onwards
char *s = "Some_string";
first of all, you are declaring a pointer to a char variable, now *s is a address in memory, and C will kick you if you try to change its memory value, thats illegal, so u better declare a character array, then assign s to its address, then change s.
Hope you get, it. For further reference and detailed understanding, refer KN King: C programming A Modern Approach
Per the language definition, string literals have to be stored in such a way that their lifetime extends over the lifetime of the program, and that they are visible over the entire program.
Exactly what this means in terms of where the string gets stored is up to the implementation; the language definition does not mandate that string literals are stored in read-only memory, and not all implementations do so. It only says that attempting to modify the contents of a string literal results in undefined behavior, meaning the implementation is free to do whatever it wants.
Related
This is from my Computer Science Class
"This is dangerous (and officially deprecated in the C++ standard) because you haven't allocated memory for str1 to point at."
— jD3V's Computer Science Professor
The Quote Above is Referring to this Line of Code
char* str1 = "Hello world";
To be clear:
I Get that using a pointer, as shown in the Line of Code above, is deprecated. I also know that it shouldn't appear in my code.
The Part I Don't Get:
The example line of code — char* str1 = "Hello world"; — works, and that surprises me.
It says that no memory has been allocated for the pointer to point at, though the pointer could still be accessed to obtain the C-String "Hello World". I am unaware of another place in memory, though my guess is that there has to be one, because if the following statement doesn't exist on the heap — "and its not placed in the stack according to my debugger" — then it must live in another memory location.
I am trying to be able to understand, and locate where the variables I declare are at in memory, and I am unable to do that here.
I would like to know...
In the example I showed above, where is the string "Hello World", and the str1 pointer that points at it, located in memory, if not in the Heap, or on the Stack?
[Disclaimer: I wrote this answer when the question was tagged both [c] and [c++]. The answer is definitely different for C versus C++. I am leaning somewhat towards C in this answer.]
char* str = "Hello world";
This is perfectly fine in C.
According to my CS Professor, in reference to the statement above, he says...
"This is dangerous (and officially deprecated in the C++ standard) because you haven't allocated memory for str to point at."
Either you misunderstood, or your professor is very badly confused.
The code is deprecated in C++ because you neglected to declare str as being a pointer to unmodifiable (i.e. const) characters. But there is nothing, absolutely nothing, wrong with the allocation of the pointed-to string.
When you write
char *str = "Hello world";
the compiler takes care of allocating memory for str to point to.
The compiler behaves more or less exactly as if you had written
static char __hidden_string[] = "Hello world";
char *str = __hidden_string;
or maybe
static const char __hidden_string[] = "Hello world";
char *str = (char *)__hidden_string;
Now, where is that __hidden_string array allocated? Certainly not on the stack (you'll notice it's declared static), and certainly not on the heap, either.
Once upon a time, the __hidden_string array was typically allocated in the "initialized data" segment, along with (most of) the rest of your global variables. That meant you could get away with modifying it, if you wanted to.
These days, some/many/most compilers allocate __hidden_string in a nonwritable segment, perhaps even the code segment. In that case, if you try to modify the string, you'll get a bus error or the equivalent.
For backwards compatibility reasons, C compilers cannot treat a string constant as if it were of type const char []. If they did, you'd get a warning whenever you wrote something like
char *str = "Hello world";
and to some extent that warning would be a good thing, because it would force you to write
const char *str = "Hello world";
making it explicit that str points to a string that you're not allowed to modify.
But C did not adopt this rule, because there's too much old code it would have broken.
C++, on the other hand, very definitely has adopted this rule. When I try char *str = "Hello world"; under two different C++ compilers, I get warning: conversion from string literal to 'char *' is deprecated. It's likely this is what your professor was trying to get at.
Summary:
"any strings in double quotes" are const lvalue string literals, stored somewhere in compiled program.
You can't modify such string, but you can store pointer to this string (of course const) and use it without modifying:
const char *str = "some string"
For example:
int my_strcmp(const char *str1, const char *str2) { ... }
int main()
{
...
const char *rule2_str= "rule2";
// compare some strings
if (my_strcmp(my_string, "rule1") == 0)
std::cout << "Execute rule1" << std::endl;
else if (my_strcmp(my_string, rule2_str) == 0)
std::cout << "Execute rule2" << std::endl;
...
}
If you want to modify string, you can copy string literal to your own array: char array[] = "12323", then your array will ititialize as string with terminate zero at the end:
Actually char array[] = "123" is same as char array[] = {'1', '2', '3', '\0'}.
For example:
int main()
{
char my_string[] = "12345";
my_string[0] = 5; // correct!
std::cout << my_string << std::endl; // 52345
}
Remember that then your array will be static, so you can't change it's size, for "dynamic sized" strings use std::string.
The problem is in lvalue and rvalue. lvalue defines locator value and it means that it has a specified place in memory and you can easily take it. rvalue has undefined place in memory. For example, any int a = 5 has 5 as rvalue. So you cannot take the address of an rvalue. When you try to access the memory for char* str = "Hello World" with something like str[0] = 'x' you will get an error Segmentation fault which means you tried to get unaviable memory. Btw operators * and & are forbidden for rvalues, it throws compile time error, if you try to use them.
The lvalue of "Hello World" is stored at the programms segment of memory. But it is specified so, as the programm can't modify it directly.
I have a Dll which I inject into my target process.
This Dll changes some variables at give memory addresses.
Normaly I do it like:
int* variable = (int*)0x????????;
*variable = 1;
Now I want to do the same thing with a string.
Reading the string works.
string* variable = (string*) 0x????????;
But changing the string crashes the process.
*variable = "hello world"; //crash
How can I fix this?
You cannot use std::string or any other non POD data type this way. What you need to do instead:
char* variable = (char*) 0x????????;
strcpy( variable, "hello world" );
or other, maybe MS specific functions to manipulate C strings.
You have not shown how you guarantee that the memory at the address 0x???????? is allocated properly or that the string object is initialized.
If the pointer does not point to allocated memory, or if the string is not initialized when you copy-assign it, then you get undefined behaviour. Possible undefined behaviour include:
But changing the string crashes the process.
To fix it, allocate and initialize a string object and use the address of that string.
I just started learning the relationship between pointers and arrays. What I read from this thread(What is the difference between char a[] = ?string?; and char *p = ?string?;?) is the string pointed by the pointer can not be changed. But in the following piece of code, I can change the string pointed by pa from abc to abd without any problem.
int main()
{
char *pa;
pa="abc";
cout<<pa<<endl<<endl;
pa="abd";
cout<<pa<<endl<<endl;
return 0;
}
However, it does not work in this piece of code. Can someone explain the difference to me? Thank you very much!!
int main()
{
char *pc;
pc="abc";
cout<<pc<<endl<<endl;
*(pc+2)='d';
cout<<pc<<endl<<endl;
return 0;
}
In the first case you are not changing the string, actually, what is happening is first you were pointing to "abc" (pa="abc";) then you are making the pointer to point to "abd" (pa="abd";), the previous string i.e."abc" remains unchanged in the memory.
And in the second case your pc pointer is pointing to the same string, and the statement *(pc+2) = d tries to modify the value pointed by pc, which cannot be done.
#user3858 I don't know whether you are aware of static,automatic and dynamic memory allocations or not but let me tell you that 'pa' is your automatic (pointer) variable initially pointing to a static memory region "abc" and which you later shifted it to point to some other memory region filled with "abd"."abc" and "abd" ,both are separate regions.And in your second program you are actually making a change in the "abc" region to make it "abd" and for which you are encountering an error.
Normally, string literals are stored in read-only memory when the program is running. This is to prevent you from accidentally changing a string constant. That's what happened in the second example, i.e. you will get a segmentation fault error.
This didn't happen in your first example because you are not changing the string itself. Instead, you just changed char *pa from pointing to one string to another.
You may need to check out: Why do I get a segmentation fault when writing to a string initialized with "char *s" but not "char s[]"?
P.S. I recommend you to use string if you do need to change some part of it.
string pc = "abc";
pc[2] = 'd';
Here, read-only "abc" is copied into non-const pc to enable you to change its content.
I'm new to C++ and I'm playing with pointers. I can't figure out why this piece of code doesn't work for me. Can you tell me what's wrong with it?
char * name = "dharman";
char *ptr = name+3;
*ptr = 'a';
printf("%s", name);
I get unhandled exception all the time.
This alone is an error:
char * name = "dharman";
The string is in constant memory but the pointer's type indicates it can be modified. Attempting to modify it produces undefined behavior: on other platforms the program will work but you got unlucky.
This was a quirk in C++03; the newer C++11 spec makes it illegal. The reason it was ever done was C compatibility.
Whether you're writing in C++ or plain C, the solution is simple:
char name[] = "dharman";
Now the compiler stores the data in read-write memory because you have asked for an array of char, not a pointer to some other memory.
String literals, like "dharman", are read-only and you cannot modify them. Instead, create and initialize an array that is not read only.
char name[] = "dharman";
name is a pointer to a string literal "dharman", which is located in read-only memory.
In your statement *ptr = 'a', you are trying to modify this string literal, which results in Undefined Behavior
It doesn't work because "dharman" is constant, it's a string literal. You cannont change it!
String literals are usually placed in read-only segments of memory.
You are trying to modify a constant string.
You need to copy the constant first to some memory that you own.
Try this:
char *name = (char*) malloc(10);
memcpy(name, "dharman", strlen("dharman"));
...
You are setting name to point at a const string and then trying to modify it. Copy the string to a modifiable location:
char *name = (char*) malloc(strlen("dharman") + 1);
memcpy("dharman", name, strlen("dharman") + 1);
The reason for unhandled exception in your case is.In your code
char *ptr= name+3;
consider the base address of name as eg:23300, so char *ptr =name+3 will be equal to
23300+(3*sizeof(char)).so now ptr points to 23300+(3*1)=23303.each element occupies one bye for char so ptr will point to letter 'a' in "dharman".since "dharman" is char const you can't its value that's why you are getting error.if u remove the line *ptr=3.the code will work without out any issue.I hope you find this post useful.
char * p_one = "this is my first char pointer";
char * p_two= "this is second";
strcpy(p_one ,p_two);
consider the above code. This is giving access violation error.
So please help to understand
where is the current "this is my first char pointer" string stored in memory? heap or stack
why I need to allocate memory for p_one before call strcpy, even it's already storing the first string. why "this is second" string cannot copy to same location?
If I allocate memory for p_one before call strcpy then what happen to "this is my first char pointer" string that was pointed by p_one ? is it keep in memory?
How strcpy knows specific pointer have allocated memory or not?
Implementation defined(usually read only) memory.[Ref 1]
You do not need to as long as you don't modify the source string literal.
If you allocate memory to p_one, then it will point to the newly allocated memory region, the string literal may/may not stay in the memory, but it is guaranteed to be alive throughout the lifetime of the program.String literals have static duration lifetime.[Ref 2]
It doesn't. It is users responsibility to ensure that.
Good Read:
[Ref 1]
What is the difference between char a[] = ?string?; and char *p = ?string?;?
[Ref 2]
"life-time" of string literal in C
First off your compiler should be warning that the p_one and p_two are actually const char * because the compiler allocates the storage of this string at compile time.
The reason you cannot modify them is because in theory you could overwrite memory after them, this is what causes hack attack with a stackoverflow.
Also the compiler could be smart and realize that you you use this string in 10 places but notices it is the same, so modifying from one place changes it - but that destroys the logic of the other 9 places that uses it
Answering all the questions in order
It's bit straight forward that your char pointer is always stored in stack. Remember even though you are using Memory allocation, it is only for determining the length of the string and appending the '\0' character.
This would be one solution, according to code you have mentioned:
int main()
{
char * p_one = "this is my first char pointer";
char * p_two= "this is second";
size_t keylen=strlen(p_two);
p_one=(char *)malloc(keylen*sizeof(char));
strncpy(p_one ,p_two,strlen(p_one));
printf("%s",p_one);
return 0;
}
When you have declared a char pointer it only points to the memory allocation. So string copy doesn't point to the end of character. Hence it is always better to use strncpy, in this conditions.
Yes it is allocating memory.
it is bad practice to cast the result of malloc as you will inhibit possible runtime errors being thrown, thanks Gewure
When you have a string literal in your code like that, you need to think of it as a temporary constant value. Sure, you assigned it to a char*, but that does not mean you are allowed to modify it. Nothing in the C specification says this is legal.
On the other hand, this is okay:
const size_t MAX_STR = 50;
char p_one[MAX_STR] = "this is my first char pointer";
const char *p_two = "this is second";
strcpy( p_one, p_two );