storage of character pointer in memory - c++

1a) There is this code
char *p;
p[0]='a';
p[1]='b';
printf("%s",p);
When i run this program on ideone.com compiler: c++ 4.3.2, it displays "RUNTIME ERROR" every single time i run it.
1b). however when i edit this code to
char *p;
//allocate memory using malloc
p[0]='a';
p[1]='b';
printf("%s",p);
It correctly runs and prints "ab" . shouldn't it require the p[2]='\0' at the end?
2)
char *p;
p="abc"
printf("%s",p);
this correctly runs and prints "abc" . why does this work without allocation.
Can anyone please explain the rules regarding string storage ?

1a) undefined behavior because you dereference a non initialized pointer
1b) undefined behavior since you call printf with %s for a non null terminated string
2) works ok: there is an allocation, it just is a string literal (you can't modify it, it is stored in the read-only portion of the program : you should declare it const char* for that reason)
Note:
In C++, use std::string and std::cout .

In the first example you declare a pointer to char and then you assign values to undefined locations in memory. Undefined because its what the uninitialize p pointer points to. You need to allocate memory for the sequence (with new[] in C++, not malloc). If you do not put a '\0' at the end, printing will stop at the first 0 encountered in memory.
In the third example you are declaring a pointer to char and initialize its value with the address of the literal string "abc". That is stored in the (read-only) data section in the executable and that gets map to the process address space. So that's a valid pointer and your printing works.

1a) here you don't allocate memory, so the p pointer points to a random place, therefore causing segfault when you write that random location
1b) if you allocate memory manually with malloc, it will work correctly. If the allocated memory contains 0s, you don't have to add it manually (but you should, because you can't count on the zero filling)
2) here you assign the p pointer to the string literal "abs", so it will point to it, and the allocation is done by the compiler

Related

Access violation at modifying char* by dereferencing [duplicate]

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.

can we declare size of a pointer

can we declare size to a pointer
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char (*ptr)=new char[3];
strcpy(ptr,"ert");
cout<<ptr<<endl;
return 0;
}
what is the meaning of this line char *ptr=new char[3] if it allocates size to ptr.since i have given the size as 3 and the string as "ert"it has to show error since the string length is too long but it doesn't .can we allocate size to pointers if so how?
You need 4 characters:
char *ptr=new char[4];
strcpy(ptr,"ert");
One extra space for the nul terminator:
|e|r|t|\0|
It's not the size of the pointer that you've declared, but the size of the character array that the pointer points to.
strcpy() does not know the length of the array that the pointer points to - it just knows it's got a pointer to the first byte it can copy into, and trusts that you know there's enough room for the copy to be made. Thus it's very fast, but it's also rather dangerous and should be used only when you're sure the destination is large enough.
strncpy() is worth looking into for some extra safety, but you still have to know that the target pointer points to something large enough for the size you specify (it protects more against the size of the source than the size of the target).
The lesson to learn here is that C and C++ won't give you any help - the compiler trusts you to get your buffer sizes right, and won't do any checking on your behalf either at compile time or runtime. This allows programs to run extremely fast (no runtime checking) but also requires the programmer to be a lot more careful. If you're writing in C++ which your tags suggest, for normal string handling you should definitely be using the std::string class unless you have a specific reason to need C-style string handling. You may well have such a reason from time to time, but don't do it unless you have to.
This statement
char (*ptr)=new char[3];
at first allocates in the heap unnamed character array with 3 elements and then the address of the first element of the array is assigned to pointer ptr.
The size of the pointer will not be changed whether you initialize it as in the statement above or the following way
char (*ptr)=new char;
that is sizeof( ptr ) will be the same and equal usually either to 4 or 8 bytes depending on the environment where the program will be compiled.
C++ does not check bounds of arrays. So in this statement
strcpy(ptr,"ert");
you have undefined behaviour of the program because string literal "ert" has four elements including the terminating zero.

c++ beginner---string modification using pointer

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.

Strlen returns unreasonable number

If I write:
char lili [3];
cout<<strlen(lili)<<endl;
then what is printed is : 11
but if I write:
char lili [3];
lili [3]='\0';
cout<<strlen(lili)<<endl;
then I get 3.
I don't understand why it returns 11 on the first part?
Isn't strlen supposed to return 3, since I allocated 3 chars for lili?
It is because strlen works with "C-style" null terminated strings. If you give it a plain pointer or uninitialised buffer as you did in your first example, it will keep marching through memory until it a) finds a \0, at which point it will return the length of that "string", or b) until it reaches a protected memory location and generates an error.
Given that you've tagged this C++, perhaps you should consider using std::array or better yet, std::string. Both provide length-returning functions (size()) and both have some additional range checking logic that will help prevent your code from wandering into uninitialised memory regions as you're doing here.
The strlen function searches for a byte set to \0. If you run it on an uninitialized array then the behavior is undefined.
You have to initialize your array first. Otherwise there is random data in it.
strlen is looking for a string termination sign and will count until it finds it.
strlen calculates the number of characters till it reaches '\0' (which denotes "end-of-string").
In C and C++ char[] is equivalent to char *, and strlen uses lili as a pointer to char and iterates the memory pointed to by it till it reaches the terminating '\0'. It just so happened that there was 0 byte in memory 11 bytes from the memory allocated for your array. You could have got much stranger result.
In fact, when you write lili[3] = '\0'
you access memory outside your array. The valid indices for 3-element array in C/C++ are 0-2.

Why my source is changing when using strcpy in c

After using strcpy source is getting corrupted and getting correct destination. Following is my code please suggest me why my source is getting corrupted? If i keep a fixed size to second character array q[] then my source is not being changed. Why is this strange behaviour. -
I am using MSVC 2005
void function(char* str1,char* str2);
void main()
{
char p[]="Hello world";
char q[]="";
function(p,q);
cout<<"after function calling..."<<endl;
cout<<"string1:"<<"\t"<<p<<endl;
cout<<"string2:"<<"\t"<<q<<endl;
cin.get();
}
void function(char* str1, char* str2)
{
strcpy(str2,str1);
}
OUTPUT:
after function calling...
string1: ld
string2: Hello world
Thanks in advance,
Malathi
strcpy does not allocate memory required to store the string.
You must allocate enough memory in str2 before you do the strcpy.
Otherwise, you get undefined behaviour as you are overwriting some non-allocated memory.
q has only space for 1 character which is the terminating \0.
Please read a book about C - you need to learn something about memory management.
Most likely your memory looks like this (simplified): Qpppppppppppp. So when you strcpy to q, you will overwrite parts of p's memory.
Since you are using C++: Simply use std::string and or std::stringstream instead of raw char arrays.
In your code, q, is an one-element array (basing on the length of "", which is equal to one due to the null terminator), so it cannot contain the whole string. Hence you can't do a strcpy because it writes over invalid memory location (tries to write too much data to an array).
Declare q to be big enough to contain your string. Also, you can use strncpy to be on the safe side.
char q[] = ""; creates a character array with exactly 1 element - copying more data into it won't reserve more memory for it.
So, what happens is that when you write past the space reserved for q, you start overwriting what's in p - the two variables are next to each other in memory.
What everyone is saying is half correct. The code is failing because space is not reserved for the copy as others have pointed out correctly. The part that's missing is that your objects are on the stack, not the heap. Therefore it is not only likely, but inevitable that your code will get corrupted as the stack can no longer be unwound.
The array "q" is just one byte long; it definitely doesn't have room for the string "Hello, World"! When you try to copy "Hello, World" to q, you end up exceeding the bounds of q and overwriting p, which is adjacent to it on the stack. I imagine drawing a diagram of how these things are laid out on the stack, you could determine exactly why the garbage that ends up in p is just "ld".
strcpy expects you to provide an allocated storage buffer, not just a char* pointer. If you change char q[]=""; to char q[50]; it will work. Since you're only giving strcpy a pointer to a zero length string it doesn't have enough space to store the copied string and overwrites aka corrupts the memory.