exception of strcpy function in c++ console program - c++

exception in strcpy();
void recid(string str,int *begin, int *end)
{
char *f,*str2;
const char c1[2]=":",c2[2]="-";
strcpy(str2,str.c_str());
f=strtok(str2,c1);
f=strtok(NULL,c2);
*begin=atoi(f);
f=strtok(NULL,c2);
*end=atoi(f);
}
could you help me to solve it?

str2 is an uninitialised pointer. strcpy does not allocate memory so is currently trying to write to an arbitrary address which you don't own and very likely isn't writable by your code.
You need to point str2 to valid memory before calling strcpy.
str2 = (char*)malloc(str.size()+1);
strcpy(str2,str.c_str());
You should also free the memory later in your program
free(str2); // cannot dereference str2 after this point

The problem is that you write in an uninitialized/random memory location by not initializing str2.
First solution:
str2 = new char[str.size() + 1];
strcpy(str2, str.c_str());
...
delete[] str2.
Second (better solution): Do not use pointers in your code unless you have to:
std::string str2 = str1;
Also, consider using std::ostringstream for tokenization into std::strings and converting to int.

Related

Do not understand about strcpy in C++

char* s1;
strcpy(s1,"smilehihi");
s1[6] = 'a';
When I compile, VS do not have any errors. But in the runtime, my code makes mistake. I think I do not really understand about strcpy
The main issue here is not the strcpy() function but the fact that you don't allocate any memory for the string itself.
If I were you, I would do something like
char* s1=(char*)malloc(SIZE); // the SIZE is the predefined maximum size of your string
strcpy(s1,"smilehihi");
s1[6] = 'a';
Edit:
Just as an advice, consider using stpncpy(). It helps to avoid buffer overflow, and, in your case, will help you avoid exceeding the maximum size of char*
char * stpncpy(char * dst, const char * src, size_t len);
The problem is that you have not allocated any space for what you wish to store in s1: "smilehihi". You declare s1 as a pointer variable, but it needs something to point at. You can allocate space by using the new operator.
char* s1 = new char[stringLength + 1]; //stringLength = length of string stored
// + 1 to hold null terminator character
strcpy(s1, "smilehihi");
s1[6] = 'a';
You have to declare #define _CRT_SECURE_NO_WARNINGS at the top of your main file to avoid an error during compilation due to strcpy() being deprecated.
You need to allocate variable first by malloc() or by using the keyword new .
Also deallocate the memory at the end
At first you should allocate char* s1.
char *s1 = new char[9]; // C++ version
or you can you use C version:
char *s1 = (char*)malloc(9);
Then you can use following code:
strcpy(s1, "smilehihi");
s1[6] = 'a';

Getting a word after a certain character?

I'm trying to make myself a program that will take a String and give me the word after a certain character. So, for example:
String theString = "hello \t world"; // or "borld \t bello";
After the tab, I only want "world" and not "hello." This keeps crashing on me for some reason.
size_t delimiter = theString.find_last_of('\t');
char *test;
if (theString.find("hello") != string::npos) {
strcpy(test, theString.substr(delimiter + 1).c_str());
else if (theString.find("borld") != string::npos) {
strcpy(test, theString.substr(delimiter + 1).c_str());
}
cout << test;
From strcpy manual:
char *strcpy(char *dest, const char *src);
The strcpy() function copies the string pointed to by src, including
the terminating null byte ('\0'), to the buffer pointed to by dest.
In your code, you declare test as a pointer to char* but you never initialize it.
test is therefore a pointer to indeterminate value. You then attempt to copy data to that inderminate location, resulting in the crash.
You can fix this easily by initializing test to point to memory you can strcpy to. Be sure to allow enough to not write beyond the buffer.
always the same mistake why you write to test without initializing it?
char *test; // no memory allocated so using it will cause a segfault
char test[50]; // just for explaining we allocate 50 bytes for pointer test
// char* test = new char[50]; // the same above but here dynamic memory
// delete[] test; // free up memory because dynamic memory is not automatically freed

difference between char [] and char* when doing strcpy

I have the following code, I wonder what is the difference between the implementation of str2 and str3, they both give the same results, which one is more prone to errors?
EDIT: when I was testing the representation of str2, I have found that one time my code crashed because str2 was a bad pointer!
/* strcpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[] = "Sample string";
char str0[] = "Sample String and more";
char* str2;
str2 = new char[40];
char str3[40];
strcpy (str2,str1);
strcpy (str3,str1);
strcpy (str2,str0);// crash happened here str2 is bad pointer!!!
printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
delete str2;
return 0;
}
Aside from the fact that str2 is a pointer whereas str3 is an array (and a pointer is a bit more trickier to use, since you may forget to delete it etc), there is another issue: the memory allocated for str2 is on the free space, via operator new. This is a slow operation. In contrast, str3 has automatic storage duration, and most often its memory is allocated on the stack, which is much faster. So in performance critical code this may make a difference.

How should I allocate memory for c-string char array?

So in attempting to learn how to use C-Strings in C++, I'm running into issues with memory allocation.
The idea here is that a new string is created of the format (s1 + sep + s2)
The text I'm using provided the header, so I can't change that, but I'm running into issues trying to set the size of char str[]. I am getting an error saying that sLength is not constant, and therefore cannot be used to set the size of an array. I'm relatively new to C++ so this is a two part question.
Is this strategy actually allocating memory for the new array?
How do I set the array size correctly if I can't get a constant value using strlen(char*)?
char* concatStrings(char* s1, char* s2, char sep){
int sLength = strlen(s1) + strlen(s2) + 3;
//+1 for char sep +2 for \0 at end of string
char *str = new char[sLength];
strcpy (str, s1);
str [sLength(s1)] = sep;
strcat (str, s2);
return str;
}
Edits made, so now I'm getting no compiler errors but...
The call to the function is here:
char* str = concatStrings("Here is String one", "Here is String two" , c);
cout<< str;
My output becomes:
Here is String onec==================22221/21/21/21/2 /(etc.)/ Here is String two
Error is returning address of local array variable str. Its scope is within function concatStrings() where you declared, and can't be accessed once control returns from the function.
To access it outside, you need to dynamically allocate memory for the string from the heap using the new operator.
char* concatStrings(char* s1, char* s2, char sep){
int s1Length = strlen(s1);
int sLength = s1Length + strlen(s2) + 2;
// +1 for sep and +1 \0 at end of string
char* str = new char[sLength];
strcpy (str, s1);
// Use strlen here instead of sizeof()
str [s1Length] = sep;
str [s1Length + 1] = '\0';
strcat (str, s2);
return str;
}
And after the program is done using the string returned from concatStrings it should ensure to free up the memory by invoking delete
char* str = concatStrings(s1, s2, sep);
// Do something
// Free up memory used by str
delete[] str;
Must use delete[] here instead of delete, or it results in undefined behaviour
I've also edited the concatStrings() function to use strlen instead of sizeof
UPDATE: Thanks for pointing out that we only need to do +2 and not +3 and for making sure a '\0' needs to be appended after str1 and sep before invoking strcat
You can allocate the resulting string memory dynamically (at run-time, on the heap), using new[] in C++ (or malloc for a more C-like style):
char* concatStrings(const char* s1, const char* s2, char sep) // enforced const correctness
{
const size_t totalLength = strlen(s1) + strlen(s2)
+ 2; // +1 for sep char, +1 for '\0'
// Dynamically allocate room for the new string (on the heap)
char* str = new char[totalLength];
strcpy(str, s1);
str[strlen(s1)] = sep; // note that you had a typo with sizeof(s1) here
strcat(str, s2);
return str;
}
Note that this memory must be released somewhere in your code, using delete[] if it was allocated with new[], or free() if it was allocated using malloc().
This is quite complicated.
You will simplify your code a lot if you use a robust C++ string class like std::string, with its convenient constructors to allocate memory, destructor to automatically free it, and operator+ and operator+= overloads to concatenate strings. See how your code is simplified using std::string:
#include <string> // for std::string
std::string str = s1;
str += sep;
str += s2;
(Note that using raw C strings can also make your code more vulnerable to safety problems, since you must pay lot of attention to proper sizing destination strings, avoid buffer overruns, etc. This is another reason to prefer a RAII robust string class like std::string.)
sizeof(s1) returns the size of a pointer variable, not the length of the array which it points to. Since you know that s1 points to a C-string, you should use the strlen() function instead.

Why does this C++ program cause a memory leak?

Consider the following piece of code:
char* str1 = new char [30];
char* str2 = new char [40];
strcpy(str1, "Memory leak");
str2 = str1;
delete [] str2;
delete [] str1;
Why does the above program cause a memory leak? How do I avoid this?
The above doesn't just lead to a memory leak; it causes undefined behavior, which is much, much worse.
The problem is in the last three lines:
str2 = str1;
delete [] str2;
delete [] str1;
If we ignore this first line, then the last two lines correctly reclaim all the memory allocated in this function. However, this first line sets str2 to point to the same buffer as str1. Since str2 is the only pointer in the program to the dynamic memory it references, this line leaks the memory for that buffer. Worse, when you then execute the next two lines to clean up the two pointers, you delete the same block of memory twice, once through str2 and once through str1. This leads to undefined behavior and often causes crashes. Particularly malicious users can actually use this to execute arbitrary code in your program, so be careful not to do this!
But there's one higher-level issue to take into account here. The whole problem with this setup is that you have to do all your own memory management. If you opt to use std::string instead of raw C-style strings, then you can write the code like this:
string str1 = "Memory leak"; // Actually, it doesn't. :-)
string str2;
str2 = str1; // Okay, make str2 a copy of str1
// All memory reclaimed when this function or block ends
Now, there's no need to explicitly manage the memory, and you don't have to worry about buffer overruns or double-frees. You're saved by the magic of object memory allocation.
Because you're deleting str1 (the memory it points to) twice and you don't delete the memory allocated under where str2 was first pointing to.
EDIT:
I'm not sure what you're trying to achieve.
char* str1 = new char [30];
// str1 = 0x00c06810; (i.e.)
char* str2 = new char [40];
// str2 = 0x00d12340; (i.e.)
strcpy(str1, "Memory leak");
// delete [] str2; should be here
str2 = str1;
// now str2 == str1, so str2 = 0x00c06810 and str1 = 0x00c06810
// deleting 0x00c06810
delete [] str2;
// deleting 0x00c06810 once again
delete [] str1;
// 0x00d12340 not deleted - memory leak
If you want that assignment (str2 = str1) then delete str2 first.
You assign str1 pointer to str2 pointer, so delete[]str1 and delete[]str2 free only memory pointed by str1 (str2 points to the same memory). You need to free str2 memory before loosing pointer to it (before assigning str1 to str2)
The correct way is
char* str1 = new char [30];
char* str2 = new char [40]; //or just don't allocate this if You don;t need it
strcpy(str1, "Memory leak");
**delete [] str2;**
str2 = str1;
delete [] str1;
make pointers to be const pointers
The problem is that you allocate memory for two arrays, you get two pointers, then you overwrite address of the second array with address of first array. So you try to free memory of the first array
Every object needs to be pointed-at in the memory.
The pointers keep track of where the data is (remember that your RAM memory is HUGE compared to the little array).
So in your case, you're losing the second array's place in memory. So there's an array lost somewhere in memory that you can't get to.
When you do str2 = str1; str2 points now to the block of memory that str1 pointed to. So there's nothing left to point at the second array.