While I was using c_str() to transform std::string into C-style string, I didn't see the last character overridden by the null-termination which c_str() is supposed to add in this program:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int main()
{
string s = "helloworld";
char c[10];
strcpy(c, s.c_str());
cout << c << endl;
return 0;
}
What I am asking is why d is being printed (added to c) as I was expecting null-termination to be there. What am I missing here?
Your code has undefined behavior, because c, the array into which you copy the string, does not allocate enough space for null terminator.
The number of characters that you copy is 10, so you need an array of 11 to accommodate the null terminator.
To avoid overrun troubles like that with statically allocated arrays, use dynamic allocation instead:
char *c = new char[s.size()+1];
strcpy(c, s.c_str());
cout << c <<endl;
delete[] c;
You have undefined behaviour, "helloworld" is actually "helloworld\0", that is 11 characters. strcpy tries to copy over the whole string including NUL but c is only able to hold 10 characters.
strcpy does not know how long the target array is. It copies until (and including) the terminating 0 byte. So, the whole string helloworld\0 is copied. Note that this is 11 chars and you might as well get a crash.
Related
Going by the books, the first cout line should print me the address of the location where the char variable b is stored, which seems to be the case for the int variable a too. But the first cout statement prints out an odd 'dh^#' while the second statement correctly prints a hex value '
ox23fd68'. Why is this happening?
#include<iostream>
using namespace std;
int main()
{
char b='d';
int a=10;
char *c=new char[10];
c=&b;
int *e=&a;
cout<<"c: "<<c<<endl;
cout<<"e: "<<e;
}
There is a non-member overload operator<<(std::basic_ostream) for the const char* type, that doesn't write the address, but rather the (presumed) C-style string1). In your case, since you have assigned the address of a single character, there is no NUL terminator, and thus no valid C-style string. The code exhibits undefined behavior.
The behavior for int* is different, as there is no special handling for pointers to int, and the statement writes the address to the stream, as expected.
If you want to get the address of the character instead, use a static_cast:
std::cout << static_cast<void*>( c ) << std::endl;
1) A C-style string is a sequence of characters, terminated by a NUL character ('\0').
Actually this program has problem. There is a memory leak.
char *c=new char[10];
c=&b;
This allocates 10 characters on heap, but then the pointer to heap is overwritten with the address of the variable b.
When a char* is written to cout with operator<< then it is considered as a null terminated C-string. As the address of b was initialized to a single character containing d op<< continues to search on the stack finding the first null character. It seems the it was found after a few characters, so dh^# is written (the d is the value of variable b the rest is just some random characters found on the stack before the 1st \0 char).
If you want to get the address try to use static_cast<void*>(c).
My example:
int main() {
char *c;
char b = 'd';
c = &b;
cout << c << ", " << static_cast<void*>(c) << endl;
}
An the output:
dÌÿÿ, 0xffffcc07
See the strange characters after 'd'.
I hope this could help a bit!
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "hello";
cout << s[5] << endl;
return 0;
}
In the above code, if I print s[5], it correctly prints a NULL character. But if I change the code to this:
#include <iostream>
#include <string>
using namespace std;
int main() {
char[] s = {'a','b','c','d','e'};
cout << s[5] << endl;
return 0;
}
It doesn't print a NULL character but something random. If I store the string as a string or as a char*, then the behavior is in tune with what I expect.
But if I explicitly declare the character array, how does the compiler know when the array ends? Does the size of the array gets stored at compile time?
String literals and std::strings store null terminated strings.
But an array of 5 char declared like:
char s[] = {'a','b','c','d','e'};
contains only 5 char, no null terminator.
But the compiler does know the size of s. It is part of the type of s. It has no convenient .size() function like std::string, std::vector or std::array does but you can get it by doing:
sizeof(s) / sizeof(s[0])
Or more safely in C++11:
std::extent<decltype(s)>::value
Or in C++17:
std::size(s)
(demo)
Arrays have a habit of decaying to pointers though and then there is no way of getting the size, you have to keep track of it yourself. Which is why std::string, std::vector or std::array is preferred in C++.
Strings are null-terminated, and const char* are treated the same way as Strings are. When you declare a array with a size it's put on the stack and the compiler doesn't know the size. Array out-of-bounds exceptions aren't determined during compile time.
the string class in c++ has the constructor which by itself adds the null character to the string passed to it if not explicitly added. But while using char it only stores the content passed to it (i.e) if you want to have a null character you have to explicitly add in the declaration or the definition of that char.
When you do char[] s = {'a','b','c','d','e'};, it will store characters mentioned and nothing else.
if I explicitly declare the character array, how does the compiler know when the array ends?
size is determined by number of characters provided by you.
Does the size of the array gets stored at compile time?
no, the size of array is determined by memory blocks allocated to it. (It is not stored separately in memory, if that's what you meant)
And when you use this string s = "hello";, strings are always null terminated.
Your code is char s[] = {'a','b','c','d','e'};, so it will not put the \0 at the end of your char array. It will put the \0 with three methods below:
1. char s[] = {'a','b','c','d','e', '\0'};
2. char s[] = "abcde";
3. string s = "abcde";
So if you use any of the three above, you will get a NULL character.
"how does the compiler know when the array ends ?": the compiler knows how many elements the array has, from its declaration, and this information is available through the sizeof operator.
Anyway C-style arrays have virtually no size, as they are implicitly turned to pointers when passed as arguments, and their length is dropped (IMO a major flaw in the design of the C language). Overflow avoidance is your responsibility.
For this reason, you mustn't use a cout << statement if your string isn't null-terminated.
I'm posting two fragments here.
The first one is giving me Segmentation Fault on deallocating the memory. Second one is working fine.
1)
int main()
{
char* ch = new char;
ch = "hello";
cout << "\n " << ch << endl;
delete[] ch; ////OR delete ch; ---> have tried both
return 0;
}
2)
int main()
{
char* ch = new char;
cin >> ch;
cout << "\n " << ch << endl;
delete[] ch; ///OR delete ch /// Both are working fine....
return 0;
}
Could anybody please tell me why the first one is failing with Segmentation Fault and second one is working fine with both delete and delete[]. Because to me both the program seems to same.
new char generates exactly 1 character (not an array of 1 character, use new char[1] for that)
so delete[] doesn't apply
in the first example, you overwrite your pointer to your allocated 1 character with a pointer to the character string "hello" - deleting this string (as it is static memory) will result in sesgfault
Edit
int main()
{
char* ch = new char; // ch points to 1 character in dynamic memory
ch = "hello"; // overwrite ch with pointer to static memory "hello"
cout<<"\n "<<ch<<endl; // outputs the content of the static memory
delete[] ch; // tries to delete static memory
return 0;
}
There are issues with both examples:
char* ch = new char;`
ch = "hello";`
The new returns an address that points to dynamically allocated memory. You must save this return value so that delete can be issued later. The code above overwrites this value with "hello" (a string-literal). You now have lost the value, and thus can not call delete with the proper value.
The second example, even though you say "works fine" is still faulty.
char* ch = new char;`
delete[] ch; ///OR delete ch /// Both are working fine....`
The wrong form of delete is used. You allocated with new, so you must deallocate with delete, not delete[]. It works this way: new->delete, new[]->delete[].
Unlike most other languages, if you go against the rules of C++, corrupt memory, overwrite a buffer, etc., there is no guarantee that your program will crash, seg fault, etc. to let you know that you've done something wrong.
In this case, you're lucky that simple types such as char* are not affected by you using the wrong form of delete. But you cannot guarantee that this will always work if you change compilers, runtime settings, etc.
There are a couple of problems with each, namely that you're only allocating a single character when you're trying to allocate a character array.
In the first example, you're also allocating a single character and then subsequently reassign the pointer to a character array - ch = "hello" will not copy the string, just reassign the pointer. Your call to delete[] will then attempt to delete a string that is not heap allocated, hence the seg fault. And you're also leaking the char you allocated, too.
In the first one, you change the pointer to point to a string literal:
ch = "hello";
String literals are static arrays, so mustn't be deleted.
The second is wrong for at least two reasons:
you allocate a single character, not an array; a single character would be deleted with delete not delete[]
cin>>ch will (most likely) read more than one character, but you've only allocated space for one.
Both of these cause undefined behaviour, which might manifest itself as a visible error, or might appear to "work fine" - but could fail when you least expect it.
To allocate an array, use new char[SIZE]; but even then, you can't prevent the user from giving too much input and overflowing the buffer.
Unless you're teaching yourself how to juggle raw memory (which is a dark art, best avoided unless absolutely necessary), you should stick to high-level types that manage memory for you:
std::string string;
string = "hello";
std::cout << string << '\n';
std::cin >> string;
std::cout << string << '\n';
there are several errors in your programs.
In the first program you are not deleting something dynamically allocated but the statically allocated string "hello". Infact when you execute ch="hello" you are not copying the string in the wrongly allocated buffer "new char" ( this new just allocates one char, not what you are looking for ) but you makes the pointer ch to point to the start of the string "hello" located somewhere in the non writable memory ( normaly that string are pointed directly into the executable ). So the delete operation is trying to deallocate something that cannot be deallocate. So the first program culd be rewritten like:
int main()
{
const char* ch = "hello";
cout<<"\n "<<ch<<endl;
return 0;
}
or like
int main()
{
char* ch = new char[strlen("hello")+1];
strcpy( ch, "hello");
cout<<"\n "<<ch<<endl;
delete[] ch; // with square brackets, it's an array
return 0;
}
Here's what's wrong with both snippets:
First snippet:
char* ch = new char; ch = "hello";
It's not legal to assign a string literal to a non-const char pointer .
Also, you re-assign the pointer immediately after you call new. The original value returned by new is now lost forever and can not be free for the duration of the program. This is known as a memory leak.
delete[] ch;
You try to deallocate the string literal. This crashes your program. You are only allowed to delete pointers that you get from new and delete[] pointers that you get from new[]. Deleting anything else has undefined behaviour.
Second snippet:
cout<<"\n "<<ch<<endl;
ch points to a single character, not a zero terminated char array. Passing this pointer to cout has undefined behaviour. You should use cout << *ch; to print that single character or make sure that ch points to a character array that is zero terminated.
delete[] ch;
You allocated with new, you must deallocate with delete. Using delete[] here has undefined behaviour.
Both are working fine....
"working fine" is one possible outcome of undefined behaviour, just like a runtime error is.
To answer the question, neither snippet is correct. First one crashes because you got lucky, second one appears to work because you got unlucky.
Solution: Use std::string.
You should use something like:
char* ch = new char[6] ;
strcpy(ch,"hello") ;
...
delete[] ch ;
I'm trying to make something similar to the strlen(str,str) function (I have a return string) to learn using pointers and the new operator, here is my code:
char* strcat(char str1[], char str2[]){
int len=strlen(str1)+strlen(str2);
char* sfin = new char[len];
int i=0;
for (i=0;i<strlen(str1);i++)
*(sfin+i)=*(str1+i); //this could be *(sfin+i)= str1[i]
for (int j=0;j<strlen(str2);j++)
*(sfin+j+i)=*(str2+j); //this could be *(sfin+i+j)= str2[j]
return sfin;
}
It works, except for the thing that the new operator allocates too much memory (or is it right?), as seen from variables watcher:
P.S. in the main() function I retrieve str1 and str2 using gets(char*) and put them using puts(char*). len has the right content (9).
Results can be various: sometimes it puts the correct string and sometimes only two "strange" characters, depending on parametres.
Null-terminated strings need to be, well, null-terminted. You only copy all the characters up to the null-terminator but not the null-terminator itself. That is, if a program looks at the content of you string, it will continue looking until it finds a null-terminator. Make sure you add a null-terminator and also make sure the memory is deleted, e.g., using
std::unique_ptr<char[]> strcat(char const* str1, char const* str2) {
// ...
std::unique_ptr<char[]> ptr(new char[len]);
// ...
return ptr;
}
BTW, your use of strlen() in each iteration of the loop is likely to result in rather bad performance, especially if you have long strings.
In c and c++, strings have to be null terminated. The resulting string contains the values of string1 and string2 but it is not null terminated. The resulting string's length should be equal to strlen(strin1)+strlen(string2)+1 and the plus 1 char can be assigned the null terminator '\0'
Here is the code:
#include<iostream>
struct element{
char *ch;
int j;
element* next;
};
int main(){
char x='a';
element*e = new element;
e->ch= &x;
std::cout<<e->ch; // cout can print char* , in this case I think it's printing 4 bytes dereferenced
}
am I seeing some undefined behavior? 0_o. Can anyone help me what's going on?
You have to dereference the pointer to print the single char: std::cout << *e->ch << std::endl
Otherwise you are invoking the << overload for char *, which does something entirely different (it expects a pointer to a null-terminated array of characters).
Edit: In answer to your question about UB: The output operation performs an invalid pointer dereferencing (by assuming that e->ch points to a longer array of characters), which triggers the undefined behaviour.
It will print 'a' followed by the garbage until it find a terminating 0. You are confusing a char type (single character) with char* which is a C-style string which needs to be null-terminated.
Note that you might not actually see 'a' being printed out because it might be followed by a backspace character. As a matter of fact, if you compile this with g++ on Linux it will likely be followed by a backspace.
Is this a null question.
Strings in C and C++ end in a null characher. x is a character but not a string. You have tried to make it one.