Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 10 days ago.
Improve this question
Why below code is throwing stack smashing detected if str1=”Overflow” & str2=”stack” but not if str1=”stack” & str2=”Overflow” ?
#include <iostream>
#include<cstring>
using namespace std;
void string_Concat (char *ptr1, const char *ptr2)
{
int length1 = strlen (ptr1);
int length2 = strlen (ptr2);
int i, j;
char *temp = ptr1;
ptr1 = new char[length1 + length2 + 1];
ptr1 = temp;
for (i = length1, j = 0; ptr2[j] != '\0'; i++, j++)
ptr1[i] = ptr2[j];
ptr1[i] = '\0';
}
int
main ()
{
char str1[] = "Overflow";
char str2[] = "stack";
string_Concat (str1, str2);
std::cout << str1 << std::endl;
return 0;
}
output :
Overflowstack
*** stack smashing detected ***: terminated
Here even if input strings are changed it should not give stack smash issue as we are allocating the sufficient space.
This is all kinds of wrong. You have multiple problems.
First, this code:
char str1[] = "...";
This allocates just enough space to store the string plus the trailing null byte. If you try appending to it, you're eventually going to run into whatever data follows it. This is BAD. You flat out can't.
Then you do this code:
char *temp = ptr1;
ptr1 = new char[length1 + length2 + 1];
ptr1 = temp;
What happens here. temp points to the value of ptr1. Then you allocate new space for ptr1 -- okay, that's cool. You then destroy the pointer and set it back to temp -- the original ptr1. This is a memory leak and accomplishes nothing at all.
The right way to do this, of course, is to use C++ strings. But you're just learning, so the second-right way to do this is almost what you have.
Allocate space the way you did (sort of), and copy both strings to it, and then return that value. Like this:
char * stringConcat(const char * str1, const char * str2) {
// get the lengths
char * newStr = new char[length1 + length2 + 1];
// append the two input strings to newStr kind of like what you did
return newStr;
}
And in main, you would do keep the returned pointer and print it kind of like you did.
Related
I have code that is supposed to remove all characters in one C-string from another.
The problem arises when I try to use the function strstr: both an array and a char* get converted to bool. Obviously it doesn't work because strstr needs to receive 2 char* arguments.
#include <iostream>
#include <ctype.h>
#include <string.h>
#include <malloc.h>
using namespace std;
char* temp_char(char* orig,char* del)
{ char *str_temp, *temp, *p, *c;
char symbol[2];
int i=0;
int len = strlen(orig);
temp=(char *)calloc(len,1);
str_temp = (char *)calloc(len,1);
strcpy(str_temp,orig);
for(i=0;i<strlen(del);i++){
symbol[0]=del[i];
symbol[1]=0;
temp[0]=0;
while( p=strstr(str_temp,del)!=NULL){
strncat(temp,str_temp,p-str_temp);
p++;
str_temp=p;
}
strcat(temp,str_temp);
strcpy(str_temp,temp);
}
cout<<temp;
return temp;
}
int main () {
char a[]="stuccsess",b[]="test";
temp_char(a,b);}
Any help would be appreciated.
You have two errors in one line of your code. The first is not addressing the issue that the != operator has higher priority than =. Thus, in the following line:
while( p=strstr(str_temp,del)!=NULL) {
the comparison is actually:
while( p = ( strstr(str_temp,del)!=NULL ) ){
So, you are attempting to assign the result of the != test, which will be a bool value, to a char* variable (p).
You can fix this, easily, by putting the assignment expression in parentheses.
However, although that will fix the compiler error, it will not address the second error. Just a few lines above that while statement, you assign one of the characters of the del string to the first of the symbol string (and, properly, add a nul terminator to that) … but you never then actually use that symbol string. Instead, you pass the entire del string as the second argument in the call to strstr. You should be passing your created symbol as that second argument.
So, changing that while line to the following will make the code work:
while ((p = strstr(str_temp, symbol)) != nullptr) { // Use nullptr in C++
But that leaves other errors in your function. How will you ever be able to free the memory allocated in the str_temp = (char*)calloc(len, 1); call? Once you have subsequently modified that str_temp pointer (in the str_temp = p; line), you no longer have the original pointer value, which must be used when calling free(). So, you need to save that value, just after you have made the allocation. (The temp memory pointer is returned, so that can be freed in the main function.)
There are other issues in your code that could be improved, like using new[] and delete[] in C++, rather than the old, C-language calloc, and that your index and length variables should really be of size_t type, rather than int. Here's a version with the corrections and suggestions discussed applied:
#include <iostream>
#include <cstring>
using std::cout;
char* temp_char(char* orig, char* del)
{
size_t len = strlen(orig);
char* temp = new char[len + 1];
char* str_temp = new char[len + 1];
char* save_temp = temp; // Save it so we can call delete...
strcpy(str_temp, orig);
for (size_t i = 0; i < strlen(del); i++) {
char symbol[2];
symbol[0] = del[i];
symbol[1] = 0;
temp[0] = 0;
char* p;
while ((p = strstr(str_temp, symbol)) != nullptr) {
strncat(temp, str_temp, static_cast<size_t>(p - str_temp));
p++;
str_temp = p;
}
strcat(temp, str_temp);
strcpy(str_temp, temp);
}
cout << temp;
delete[] save_temp; // ... don't forget to free this.
return temp;
}
int main()
{
char a[] = "stuccsess", b[] = "test";
char* answer = temp_char(a, b);
delete[] answer; // We should free the memory allocated!
return 0;
}
But your approach is far more complicated than it need be. You can simply loop through the original string and check each character to see if it is in the 'delete' string (using the strchr function, for example); if it is not (i.e. that strchr returns nullptr), then append the character to the accumulated temp and increase the running length:
char* temp_char(char* orig, char* del)
{
size_t len = strlen(orig);
char* temp = new char[len + 1];
int newlen = 0;
for (char* cp = orig; *cp != '\0'; ++cp) {
if (strchr(del, *cp) == nullptr) temp[newlen++] = *cp;
}
temp[newlen] = '\0'; // Add null terminator
std::cout << temp;
return temp;
}
I am creating a function to split a char * into an array of other char * based on a target (which can be " ", "a", etc). In this example, I am using a white space (" ") to split my char * into an array of char *.
However, I am having some difficulties dealing with the dynamically allocated memory. I allocated memory for both the array of char * that I will be returning as the split function return value, and another one to copy each separated const * that I am reading from the main char * parameter.
#define MAX_SIZE 65535
#define MAX_SPLIT_SIZE 1023
char** a_split(char * x, const char * target, int sn){
char ** sa = nullptr;
size_t t_len = strnlen(target, MAX_SIZE);
if(t_len < 1 || t_len > MAX_SIZE){ return sa; }
int split_num = 0;
if(sn > 1 && sn < MAX_SPLIT_SIZE){
sa = new char * [sn + 1]();
split_num = sn;
}else if(sn == -1){
sa = new char * [MAX_SPLIT_SIZE + 1];
split_num = MAX_SPLIT_SIZE;
}else {
return sa;
}
char * ptr = x;
char * mi; // Match index.
int i = 0; // Index of 'sa' array.
while((mi = std::strstr(ptr, target)) && split_num--){
size_t dif = mi - ptr;
char * n_cstring = new char[dif + 1]();
memcpy(n_cstring, ptr, dif); // Copying content to new string.
sa[i++] = n_cstring; // Append new string to 'sa' array of split strings.
ptr += dif;
ptr += t_len;
delete [] n_cstring; // <------- This is causing some weird errors.
}
if(mi == nullptr){
sa[i] = ptr;
}
return sa;
}
int main(int argc, char * argv[]){
char c[] = "I love Thanos";
char ** x = a_split(c, " ", -1);
for(int i = 0; x[i]; i++){
puts(x[i]);
}
return 0;
}
I found out that when using 'delete [] n_cstring', instead of outputting the char *'s separately (like in "I" "love" "Thanos"), it is outputting "love" "love" "Thanos". It is making this kind of repetition for every example. Why is 'delete' doing this?
Also, as I am returning a dynamically allocated array ('sa'), where would you recommend me to delete it? - the main function does not recognize 'sa'.
One problem is that you are deleting n_cstring too soon: since you are storing it in sa[] array, i.e.
sa[i++] = n_cstring;
deleting it right after that in the loop leaves sa[i] hanging. The end result is that your main would have undefined behavior, in addition to having memory leaks due to never deleting sa.
I am returning a dynamically allocated array (sa), where would you recommend me to delete it?
There is only one place where this could be done - it's main. You put sa into x, so you need to invoke delete[] x once you are done printing.
Note that since delete[] n_cstring must be removed from a_split function, main must also delete the individual elements of x before deleting x itself.
The best approach by far is to change your code to use std::vector<std::string>. This would free you from allocating and deleting character arrays, fixing potential crashes automatically.
I have been given a task, where I need to create the string_copy function Note that the function body and prototypes have been given by the source and that needs to be maintained. The portions written by me are after the comment write your code here.
#include <iostream>
using namespace std;
int string_length(const char* string_c);
char* string_copy(const char* string_c);
int main()
{
const char* string_c = "This is a string and is a long one so that we can create memory leaks when it is copied and not deleted";
// write your code here
int length = string_length(string_c);
cout << "Copied String: " << string_copy(string_c) << endl;
return 0;
}
int string_length(const char* string) {
int length = 0;
for (const char* ptr = string; *ptr != '\0'; ++ptr) {
++length;
}
return length;
}
char* string_copy(const char* string) {
// we need to add 1 because of ’\0’
char* result = new char[string_length(string) + 1];
// write your code here (remember zero-termination !)
int i;
for (i = 0; string[i] != '\0'; ++i)
{
result[i] = string[i];
}
result[i] = '\0';
return result;
}
Now task tells me
that it is very important that any memory allocated with e=new TYPE is
released later with delete e (and a=new TYPE[size] with delete [] a)
else this will lead to an error.
It is not exactly clear if error means compile/runtime error or error as in my task did not meet the requirement error.
My question is, in this code how do I delete the intermediate dynamically created result array? If I delete result, won't it fail the purpose of the task? Then how am I to respect the quotation above or maybe simulate memory leak as given in the long string constant?
Thanks.
EDIT: Why the negative votes? Please at least explain the reason! I am not asking any solution or something, but mere suggestion if I am missing some point or not!
The caller of string_copy would be responsible for releasing the memory when it's done with it by calling delete[] on it.
This is, by the way, a terrible way to write C++ code. You should be using std::string or std::vector<char> or something like that.
Here's why:
int length = string_length(string_c);
char* copy = string_copy(string_c);
cout << "Copied String: " << copy << endl;
delete[] copy;
return 0;
Yuck.
In fact the ideal solution is to use std::string and not char *. There is no real need of using char * instead of std::string in your example.
With std::string:
You don't need to new anything
You don't need to delete anything
You can do everything with std::string, that you do with char *.
Hi guys I'm writing a program that reads NMEA sentences for a university assignment and I'm having trouble with segmentation fault. Can anyone help me fix it, please?
NmeaSentence::NmeaSentence(std::string sentence) {
const char *temp = sentence.c_str();
char *c_sent;
strcpy(c_sent, temp);
char *pch;
for(int i = 0; i < MAX_SENTENCE_PARTS; i++){
pch = strtok(c_sent, ",");
this->sentenceParts[i] = pch;
}
this->sentence = sentence;
this->sentenceType = sentenceParts[0];
}
The error seems to be happening at strcpy. What am I doing wrong?
You don't allocate memory for c_sent. That's undefined behaviour.
Use char *c_sent = new char[sentence.size() + 1];. I've added space for the null terminator. Don't forget to call delete[] c_sent; before the function exits.
(By the way, temp is valid for the lifetime of sentence, unless it's modified in any way.).
The temporary string c_sent is uninitialized.
char * c_sent
to
char * c_sent = strdup(sentence.c_str());
Dont forget to free, before exit.
free(c_sent);
You won't need temp this way.
The member function has several defects.
If the parameter of the function is not changed then it would be better to declare the function as
NmeaSentence::NmeaSentence( const std::string & sentence);
As it was already said you did not allocate memory where you are going to copy sentence. Pointer c_sent was not initialized by the address of an allocated memory.
The second defect is that pch always points to the same address in c_sent because you are incorrectly using function strtok. You should use it the following way
char *pch = strtok(c_sent, ",");
for(int i = 0; i < MAX_SENTENCE_PARTS && pch; i++){
this->sentenceParts[i] = pch;
pch = strtok( NULL, ",");
}
Also it is not clear how you will determine how many parts the string contains.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
cout<<str;
return 0;
}
The first program gives output Sivaœ> i.e siva with some garbage values....
But the second program show segmentation fault...Please help me to find out
exact answer...
#include<iostream>
using namespace std;
int main()
{
int i=0;
char *name="Siva",*str;
for(i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
cout<<str;
return 0;
}
char *name="Siva",*str;
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str is a pointer, but it doesn't yet point to anything.
Since you're in C++, you should be using std::string:
#include<iostream>
#include <string>
using namespace std;
int main()
{
char *name="Siva";
std::string str;
for(int i=0;i<strlen(name);i++)
{
str += name[i];
}
cout<<str;
return 0;
}
Even better, get rid of the hand-written loop:
#include <algorithm>
int main()
{
char *name="Siva";
std::string str;
std::copy (name, name + strlen (name), std::back_inserter (str));
cout<<str;
return 0;
}
Better even still, there's no reason in this particular example why you need to do any of that at all:
char* name = "Silva";
std::string str = name;
cout << str;
By the way, string literals in C++ are inherently const:
const char* name = "Silva";
If you really must use a char*, first I would strongly question why, and then I would tell you to do this:
int main()
{
const char *name="Siva";
char* str = new char [strlen (name)+1]; // +1 for the null terminator
strcpy (name, str);
cout << str;
delete [] str;
return 0;
}
I would even more strongly question your need to copy it byte-by-byte:
int main()
{
const char *name="Siva";
char* str = new char [strlen (name)+1]; // +1 for the null terminator
for (size_t i = 0; i < strlen (name); ++i )
str [i] = name [i];
str [strlen (name)] = '\0';
cout << str;
delete [] str;
return 0;
}
You have undefined behaviour here:
str[i]=name[i];
str has not been initialized to anything. You are writing to places you shouldn't.
There are two problems with this.
The pointer str doesn't point to allocated memory, so writing through it is undefined behavior.
Even if it did point to valid memory, you're not writing the correct amount of data. When copying a string, you need to copy the 0 byte at the end which marks the end of the string; so the upper limit of your loop should bt strlen(name) + 1. Or you could use a library method like strdup() instead of your own for loop.
The reason the "working" version prints some garbage characters is that there's no 0 at the end of the copied string to tell iostreams to stop printing. The reason the "working" one doesn't crash, and the other one does, is pure dumb luck: the garbage in str, by chance, points to memory you're allowed to write to, while in the crashing program, it points to memory you're not allowed to write to. Simple as that.
It is because you have no memory allocated for str. (it will cause an undefined behavior)
You can mix that by using a merory allocation function like in this example :
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
// Allocate memory with malloc
str = (char*)malloc( (strlen(name)+1) * sizeof(char) );
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[strlen(name)] = 0;
cout<<str;
// Free the allocated memory
free(str);
return 0;
}
As you are using c++, you can do :
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
// Allocate memory with new
str = new char[strlen(name) + 1];
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[strlen(name)] = 0;
cout<<str;
// Free the allocated memory
delete []str;
return 0;
}
EDIT :
The reason you have some weird caracters at the end of your ouput is that because you string is not terminated with a '\0', it will continue to print it. (This will occur only if you don't have a segmentation fault )
There are a couple problems with your code.
Firstly, *str is not allocated, so it starts off by pointing to whatever bit of memory the pointer value happens to start off as.
Secondly, strlen() returns the length of the string excluding the terminating null character. So what you are doing is copying all the values of name into some random bit of memory, not terminating it, then telling the system to print that off, which could be any length.
str[i]=name[i]; is illegal, causes Undefined behavior, because you have not allocated memory for str.
Before for loop allocate memory for destination string str:
str = malloc (strlen(name) + 1 );
Also you forgetting string termination, after for-loop add terminate string str[i] = '\0';
Undefined behavior refers to computer code whose behavior is unpredictable.
You code should be:
char *name="Siva", *str;
str = malloc (strlen(name) + 1 ); // mistake
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[i] = '\0'; // forgetting
To understand further you can read this answer: strcat() implementation works but causes a core dump at the end
Your problem is using char arrays and pointers to represent strings in language which has proper string type.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name = "Siva", str;
str = name;
cout << str;
return 0;
}
Problem is with str[i]=name[i] you must know that C++ does not care for memory leaks
as Java or some others. So you must allocate memory to a variable or pointer in order to avoid these problems. Already there are number of answers, you can also try
str=new char[strlen(name)+1];
and do not forget to terminate the char array with null when you done copy. In this case
str[strlen(name)]='\0';