While running following code, my program crashes unexpectedly!
#include<stdio.h>
#include<string.h>
int main(){
char *str = NULL;
strcpy(str, "swami");
printf("%s", str);
return 0;
}
But if I do like this:
#include<stdio.h>
#include<string.h>
int main(){
char *str;
strcpy(str, "swami");
printf("%s", str);
return 0;
}
This code works fine and generates correct output!
I am using gcc compiler(codeblocks IDE). Also, both the codes lead to program crash in DevCpp. Can anyone please explain me why this is so!?
You cannot write to NULL pointers.
In the second case, it happened that your pointer was randomly initialized to a valid location in your program's memory. That is why you could do a strcpy into it.
Change both programs to have
str = malloc(size)
or the option with calloc before the strcpy. (size is the size of the space you want to reserve.)
As per comment, you can also change the declaration of str to be char str[6] (or more).
Last edit: I'll present you this picture showing the memory of your program and the pointers:
The gray areas and the red one are forbidden (you cannot write or read from them; the top gray one is for kernel memory while the others are spaces not yet reclaimed). The red area at the bottom is the special 0 page. Since NULL is 0 your str = NULL will point to this and your program will fail.
If you don't assign anything to str it will end up pointing randomly. It can still point to the red area or to a grey area -> your program will fail. It could point to a green or blue (both hues) area, making your program work (excepting the cases where it is pointing to a read-only location and you write to it). Allocating area for the pointer makes it point to the green area, enlarging it to the top.
The other option, with str[6] enlarges the stack area to bottom. All local variables have space reserved into the stack while all space allocated with malloc, realloc, calloc and other friends goes into the heap.
Lastly, have a look at a blog article about the difference between char[] and char *.
PS: If you'd want to use a GNU extension you can look into the asprintf function. It would allocate space for a string and write some content there:
asprintf(&str, "swami");
or
asprintf(&str, "%d + %d == %d\n", 1, 2, 3);
But, if you want portability, you'd stay away from this function.
In neither version have you allocated memory to copy the string to, so both invoke undefined behaviour. The first one crashes because you explicitly initialised str to NULL, so the strcpy dereferences a NULL pointer, that crashes on most systems. In the second, str points to arbitrary memory, dereferencing that uninitialised pointer may or may not crash.
Because NULL is #define NULL ((void *)0) in <stdlib.h>. So, you try to write in invalid memory address that make your program crash.
Read this link
//destination =Pointer to the destination array where the content is to be copied.
char * strcpy ( char * destination, const char * source );
You're setting destination to NULL, so you're trying to copy source to NULL. That's why it crashes. You should be setting some memory asside to copy the string to instead.
int main(){
char *str=malloc(6); //enough for "swami"+'\0'
strcpy(str, "swami");
printf("%s", str);
return 0;
}
strcpy just copies, not generating space for it.
in the first case you tried to write the string to the beginning of the code segment: not a good idea.
in the second case, you started writing the string to somewhere, and in your case didn't crash do to luck and maybe compiler help.
you should do one of the following:
a. allocate memory: str = new char[10]
b. use strdup witch well duplicate the string into a new location.
Related
As I understood the correct programming style tells that if you want to get string (char []) from another function is best to create char * by caller and pass it to string formating function together with created string length. In my case string formating function is "getss".
void getss(char *ss, int& l)
{
sprintf (ss,"aaaaaaaaaa%d",1);
l=11;
}
int _tmain(int argc, _TCHAR* argv[])
{
char *f = new char [1];
int l =0;
getss(f,l);
cout<<f;
char d[50] ;
cin>> d;
return 0;
}
"getss" formats string and returns it to ss*. I thought that getss is not allowed to got outside string length that was created by caller. By my understanding callers tells length by variable "l" and "getcc" returns back length in case buffer is not filled comleatly but it is not allowed go outside array range defined by caller.
But reality told me that really it is not so important what size of buffer was created by caller. It is ok, if you create size of 1, and getss fills with 11 characters long. In output I will get all characters that "getss" has filled.
So what is reason to pass length variable - you will always get string that is zero terminated and you will find the end according that.
What is the reason to create buffer with specified length if getss can expand it?
How it is done in real world - to get string from another function?
Actually, the caller is the one that has allocated the buffer and knows the maximum size of the string that can fit inside. It passes that size to the function, and the function has to use it to avoid overflowing the passed buffer.
In your example, it means calling snprintf() rather than sprintf():
void getss(char *ss, int& l)
{
l = snprintf(ss, l, "aaaaaaaaaa%d", 1);
}
In C++, of course, you only have to return an instance of std::string, so that's mostly a C paradigm. Since C does not support references, the function usually returns the length of the string:
int getss(char *buffer, size_t bufsize)
{
return snprintf(buffer, bufsize, "aaaaaaaaaa%d", 1);
}
You were only lucky. Sprintf() can't expand the (statically allocated) storage, and unless you pass in a char array of at least length + 1 elements, expect your program to crash.
In this case you are simply lucky that there is no "important" other data after the "char*" in memory.
The C runtime does not always detect these kinds of violations reliably.
Nonetheless, your are messing up the memory here and your program is prone to crash any time.
Apart from that, using raw "char*" pointers is really a thing you should not do any more in "modern" C++ code.
Use STL classes (std::string, std::wstring) instead. That way you do not have to bother about memory issues like this.
In real world in C++ is better to use std::string objects and std::stringstream
char *f = new char [1];
sprintf (ss,"aaaaaaaaaa%d",1);
Hello, buffer overflow! Use snprintf instead of sprintf in C and use C++ features in C++.
By my understanding callers tells length by variable "l" and "getcc" returns back length in case buffer is not filled comleatly but it is not allowed go outside array range defined by caller.
This is spot on!
But reality told me that really it is not so important what size of buffer was created by caller. It is ok, if you create size of 1, and getss fills with 11 characters long. In output I will get all characters that "getss" has filled.
This is absolutely wrong: you invoked undefined behavior, and did not get a crash. A memory checker such as valgrind would report this behavior as an error.
So what is reason to pass length variable.
The length is there to avoid this kind of undefined behavior. I understand that this is rather frustrating when you do not know the length of the string being returned, but this is the only safe way of doing it that does not create questions of string ownership.
One alternative is to allocate the return value dynamically. This lets you return strings of arbitrary length, but the caller is now responsible for freeing the returned value. This is not very intuitive to the reader, because malloc and free happen in different places.
The answer in C++ is quite different, and it is a lot better: you use std::string, a class from the standard library that represents strings of arbitrary length. Objects of this class manage the memory allocated for the string, eliminating the need of calling free manually.
For cpp consider smart pointers in your case propably a shared_ptr, this will take care of freeing the memory, currently your program is leaking memory since, you never free the memory you allocate with new. Space allocate by new must be dealocated with delete or it will be allocated till your programm exits, this is bad, imagine your browser not freeing the memory it uses for tabs when you close them.
In the special case of strings I would recommend what OP's said, go with a String. With Cpp11 this will be moved (not copied) and you don't need to use new and have no worries with delete.
std::string myFunc() {
std::string str
//work with str
return str
}
In C++ you don't have to build a string. Just output the parts separately
std::cout << "aaaaaaaaaa" << 1;
Or, if you want to save it as a string
std::string f = "aaaaaaaaaa" + std::to_string(1);
(Event though calling to_string is a bit silly for a constant value).
I have a confusion while dealing with char pointers. Please have a look at following code:
class Person
{
char* pname;
public:
Person(char* name)
{
//I want to initialize 'pname' with the person's name. So, I am trying to
//achieve the same with different scenario's
//Case I:
strcpy(pname, name); // As expected, system crash.
//Case II:
// suppose the input is "ABCD", so trying to create 4+1 char space
// 1st 4 for holding ABCD and 1 for '\0'.
pname = (char*) malloc(sizeof(char) * (strlen(name)+1) );
strcpy(pname, name);
// Case III:
pname = (char*) malloc(sizeof(char));
strcpy(pname, name);
}
void display()
{
cout<<pname<<endl;
}
};
void main()
{
Person obj("ABCD");
obj.display();
}
For Case I:
As expected, system crash.
Output for Case II:
ABCD
Output for Case III:
ABCD
So, I am not sure why Case II & III are producing the same output !!!!.....
How I should initialize a char pointer in a class?
The third case invokes Undefined Behavior and so anything might happen in that case.
You are writing beyond the bounds of allocated memory in this case which may or maynot crash but is a UB.
How to do this the right way in C++?
By not using char * at all!
Just simply use std::string.
Note that std::string provides you with c_str() function which gets you the underlying character string. Unless, You are bothered about passing ownership of a char * to a c-style api you should always use std::string in c++.
The third option is also wrong as you haven't allocated enough memory for it. You're trying to copy a string of size 5 to a buffer of size 1, which means the data after pname[1] are incorrectly overwritten and gone..
If you're lucky, you may see a runtime error such as memory access violation, or you won't see anything but the data behind it is corrupted, e.g., your bank account, and you never know about it until..
The correct way to go is to always allocate enough memory to copy to. A better way in C++ is to use std::string, as Als points out, because it'll free you from manual management of memory (allocation, growing, deallocation, etc).
E.g.,
class Person
{
std::string pname;
public:
Person(char* name)
{
pname = name;
}
void display()
{
cout << pname << endl;
}
};
void main()
{
Person obj("ABCD");
obj.display();
}
You have to allocate memory for your member variable pname, however, I don't know why you want to use a char* when you can just use a string:
std::string pname;
//...
pname = std::string(name);
If there is a good reason why you must use a char*, then do something of the sort:
// initialize the pname
pname = new char[strlen(name)];
// copy the pname
strcpy(pname, name);
The reason why you don't need to allocate an extra space at the end of the string for null-termination is because using the double quotes "blah" automatically produces a null-terminated string.
If you are into C++ business, then it's time to dump char pointers on behalf of STL string:
#include <string>
class Person
{
std::string the_name;
public:
Person(std::string name) : the_name(name)
{ ...
Also cout is used the same.
In your Case III, you do pname = (char*) malloc(sizeof(char));, which allocates enough memory for a single char. However, strcpy has no way of knowing that, and writes over whatever memory comes directly after that byte, until it has finished copying over all of the char* you passed into the function. This is known as a buffer overflow, and while this might immediately work, it could possibly break something down the road. If you are looking to copy only a subsection of the char*, you could look into strncpy, which copies up to some length (API reference here). If you use that, be sure to add the null-terminating character yourself, as strncpy will not include it if you copy only part of the string.
That pname = (char*) malloc(sizeof(char)); works is coincidental, the call to strcpy writes into memory that hasn't been allocated, so it could crash your program at any time.
A simpler way to initialize your buffer would be:
pname = strdup(name);
or
pname = strndup(name, strlen(name));
See http://linux.die.net/man/3/strdup.
Also, you must think about freeing the memory allocated by calling free(pname); in the class destructor.
All in all, all of this can be avoided by the use of the C++ std::string class, as mentioned by everyone.
Correct is case II!
Yes, case I is wrong, it will crash since you are copying data to a non initialized pointer.
Case III is also wrong, but it works now because your test string is small! If you try with a bigger string it will corrupt memory since you are copying a big string to a small allocated space.
In some systems malloc works with clusters so it works by allocating chuncks of memory instead of allocating byte-by-byte. This means that when you used malloc to alocate a single byte (like you did in case III), it allocates some more up to reach the minimum block of memory it can handle, that's why you could move more then 1 byte to it without crashing the system.
I was reviewing my skills with pointers and buffer in C++. I tried the code below and everything works fine. No leaks, no crash, nothing.
To be honest I didn't expect this.
When I call char* buf2 = new char[strlen(buf)] I didn't expect srlen(buf) returning the right size. I always thought that strlen
needs a NULL terminated string to work. Here it is not the case so why it is working this code?
int main(){
const char* mystr = "mineminemine";
char* buf = new char[strlen(mystr)];
memcpy(buf, mystr, strlen(mystr));
char* buf2 = new char[strlen(buf)];
memcpy(buf2, buf, strlen(buf));
delete[] buf2;
delete[] buf;
}
That's called undefined behavior - the program appears working but you can't rely on that.
When memory is allocated there happens a null character somewhere that is close enough to the start of the buffer and the program can technically access all memory between that null character and the start of the buffer so you don't observe a crash.
You can't rely on that behavior. Don't write code like that, always allocate enough space to store the terminating null character.
Consider another way to do the same thing:
int main(){
std::string mystr = "mineminemine";
std::string mystr2 = mystr;
}
Internally you have a buffer with a null terminating character added. When you copy a standard string you don't have to worry about keeping track of the start and end of the buffer.
Now considering the lifetime of the strings these two variables are declared on the stack and destroyed when main goes out of scope (e.g. terminationa). If you need strings to be shared amongst objects and you do not necessarily know when they will be destroyed I recommend considering using boost shared pointers.
note: please suppress comments about "C++? Use std::string!". This question is using C strings but is more about memory management than strings in general.
I have this function
char* strclone( char* src )
{
char* dst = (char*)malloc(strlen(src+1));
strcpy(dst,src);
return dst;
}
The function should work to allocate a new pointer (in strclone), write the string in src to it, and return the address of the new string.
However, when the string is freed, some time later in the program:
str = strclone( some_str_variable );
// ..code..
free( str ) ; //! ERROR!
The error reads:
Debug Error!
Program: C:\...
HEAP CORRUPTION DETECTED: after Normal block (#39713) at 0x090CC448.
CRT detected that the application wrote to memory after end of heap buffer.
The error occurs at the line where I call free( str ) in the program. If I change the assignment of str to this:
str = (char*)malloc( strlen( some_string_variable ) +1);
strcpy( str, some_string_variable ) ;
//...
free( str ) ; //fine now
Then there is no bug, the program functions perfectly.
Why does the strclone function not work as expected?
I believe that the problem is that you've written
(char*)malloc(strlen(src+1));
Notice that in the call to strlen, you have written
strlen(src + 1)
instead of
strlen(src) + 1
This first line says "the length of the string starting one character past src," which is the length of the string minus one (or total garbage if the string is empty). The second one is the one you want - the length of the string plus one for the null terminator. If you use the first version, then in the line
strcpy(dst,src);
You will end up writing past the end of the buffer, leading to the dreaded Undefined Behavior. In your case, this was manifesting itself with a heap corruption error when you try to free the block, which makes sense because you have indeed corrupted the heap!
Try moving the +1 out of the parentheses and see if it fixes things.
Alternatively, most compilers ship with a nonstandard function called strdup that does exactly what your above function attempts to do. You might want to consider just using that instead.
Hope this helps!
strlen(src+1) is not the same as strlen(src)+1. So you are overwriting the bounds of your array by two elements when you do to the strcpy.
So I think the following is justified: C++? Use std::string!
I believe you should have typed
char* dst = (char*)malloc(strlen(src) + 1);
instead of
char* dst = (char*)malloc(strlen(src+1));
The error happens because you are actually writing past the allocated memory.
change your malloc line to this:
char* dst = (char*)malloc(strlen(src)+1);
Because in your original implementation, you're advancing the pointer by 1, and then you pass that to strlen(), which will give you the lenght of the string-1. Since you also need the NULL at the end, you're actually off-by-2.
Try this:
malloc(strlen(src)+1);
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.