Segmentation Fault in C++ most probably in strtok operation - c++

I was writing a postfix evaluation program which could handle multiple digits. Therefore I first read the inputs to a character array, and split them to array of (character array). Whenever I run my program, it gives a segmentation error (g++ on Ubuntu 13.10)
Here's my function to split
int split(char str[], char *ret[]){
int c=0;
char * pch;
pch = strtok (str," ");
while (pch != NULL)
{
//printf ("%s\n",pch);
strcpy(ret[c], pch); c++;
//cout<<ret[c];
pch = strtok (NULL, " ");
}
return c;
}
And part of my main()
char* s;
s = new char[200];
cout<<"Enter Postfix Expression:\n > ";
cin.getline(s,200);
char* st[200];
//int size=3;
int size = split(s, st); // < Is what I'm passing correct?
I could not understand why the segfault occurred. Any suggestions?
EDIT: Thanks to yugnum for the answer. The following did the trick
...
ret[c] = new char[strlen(pch)];
strcpy(ret[c], pch); c++;
...

char* st[200];
int size = split(s, st);
int split(char str[], char *ret[]){
...
strcpy(ret[c], pch);
...
}
this is what is wrong, you just pass bunch of uninitialized pointers to strcpy while it requires pointer that points to valid allocated memory.

You need to define st as 2D array, so split function will return an array of split strings
For example:
char st[20][200]
and then:
int split(char str[], char *ret[][]){
So you'll have 20 of 200 byte char array.
But it's not safe at all, I suggest you considering something else like vector or std::string. Also you need to allocate your array before strcpy.
Then
strcpy(ret[c], pch);
with c as counter, will copy split new string to your char array.
But consider std::string, which is best choice

Related

Segmentation fault when trying to get string from input

#include <iostream>
using namespace std;
int main() {
char *s;
printf("enter a word \n");
scanf("%s", s);
int i;
for (i = 0; s[i] != '\0'; i++) {
}
printf("length is = %d", i);
return 0;
}
When I compile this program, a segmentation fault occurs.
Can anyone plz tell me, what is the problem in this code?
char *s;
Is unitialized, you can't assign an input stream to it until it is.
char s[100]; //space for 99 characters plus null terminator
or
char* s = malloc(100); //each char has the size of one byte
These are C tools, for C++, however, you can/should use std::string, with std::cin instead of scanf.
std::string s;
std::cin >> s;
If you must use C tools, scanf("%s", s); is not the most safe method, if you don't pass the size of the char array container, changing specifier %s to %100s or changing it altogether to a safer function like fgets(s, sizeof(s), stdin); is a better option.
char *s;
You created a pointer, though it does not point to anything (it is uninitialized).
scanf("%s",s);
You try to read data into the string pointed-to by s, but no such thing exists.
💥!
Allocate some memory and have s point to it… or, better yet, use std::string and std::cin.
char *s;
printf("enter a word \n");
scanf("%s",s);
scanf with %s does not allocate memory, instead it reads into the buffer you provide it (e.g. s = malloc(100);. How big does that buffer need to be to avoid a buffer overflow? Unfortunately it can be however long until a whitespace character, so is inherently unsafe.
You can specify a max up front (not including null terminator!), but to handle variable size you then need to dynamically build the format string which gets complicated. As does what to do if the user enters a string too long.
char s[100];
scanf("%99s", s);
Since you tagged C++, you can use std::string and IO streams (e.g. std::cin for console input) which will handle all the memory allocation for you.
std::string s;
std::cout << "enter a word" << std::endl;
std::cin >> s;
In the case of C, you might use fgets(str, num, stream), this lets you specify the max length and avoid overflow in a simple manner.
char s[128];
fgetsf(s, 100, stdin);
Or with the POSIX 2008 scanf it can allocate the memory, but I don't believe this is universally supported, e.g. by Microsoft Visual Studio.
char *s = 0;
scanf("%ms", &s); // pass a pointer to a pointer!
free(s); // needs to be freed later!

Memcpy Char Pointers

I have this simple program in which I want to concatenate two char pointers using memcpy, but I get access violation reading location on the memcpy line.
char *first = new char[10], *second=new char[10];
first="Hello ";
printf("\second: ");
scanf("%s",&second);
memcpy(first,second,strlen(second)+1);
printf ("Result: %s\n", first);
Because copying into a constant gets me the violation, I tried this:
char *first = new char[20], *second="world!";
printf("first: ");
scanf("%s",&first);
memcpy(first,second,strlen(second)+1);
printf ("Result: %s\n", first);
which gets me access violation writing location. How should I concatenate correctly the two pointers?
Your memcpy is equivalent to memcpy ("Hello ", second, strlen(second)+1);. Copying into a constant is (on some platforms, apparently including yours) an access violation.
char *first = new char[10], *second=new char[10];
first="Hello ";
First you make first point to some memory you allocated. Then you throw that pointer away and make it point to a static string. That's not what you mean. Maybe you meant:
strcpy (first, "Hello ");
This copies the constant's data into the space first points to.
char * concat(const char * first, const char * second)
{
int lf = strlen(first);
int ls = strlen(second);
int len = lf + ls;
char * rb = new char[len+1];//You need this +1 here
memcpy(rb, first, lf);
memcpy(rb+lf, second, ls);
rb[len] = 0;
return rb;
}
int main ()
{
char *first = new char[10], *second=new char[10];
strcpy(first, "first");//This is an unsafe way. You can take the value from anywhere possible
strcpy(second, "second");//This is an unsafe way. You can take the value from anywhere possible
char * third = concat(first, second);
cout << third << endl;//Don't use cout << concat(first, second) << endl; since it leads to a emory leak
delete [] third;
return 0;
}
You can't concatenate two string without using extra memory, since every time you need a memory block of size of the sum +1 (or more) of the two given strings.
Change
scanf("%s", &first);
to
scanf("%s", first);
You access the wrong memory when scaning.

Segmentation fault in constructor when using strcpy

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.

Convert vector<string> * char to int

I need help in my following code and hope that you can help me through. All I wanted is to pass in INT type to setX() and setY(). However, there is no way for me to convert vector char* to int. Is there alternative to this?
template<class T>
vector<string> Delimiter(T inputString){
int count=0;
char str[inputString.length()];
strcpy(str,inputString.c_str());
char * pch;
vector<string> returnContainer;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str,",[]");
while (pch != NULL)
{
returnContainer.push_back(pch);
pch = strtok (NULL, " ,[]");
count++;
}
for(int i=0; i<returnContainer.size(); i++){
cout << "return:" << returnContainer[i] << endl;
}
return returnContainer;
}
//Main()
fileDataAfterFiltered = Delimiter(fileData[i]); // Delimiter (vector<string> type)
point2DObj[point2DCount].setX(fileDataAfterFiltered[1]); // error
point2DObj[point2DCount].setY(fileDataAfterFiltered[2]); // error
//Assn3.cpp:107:59: error: no matching function for call to ‘Point2D::setX(std::basic_string&)’
Delimiter() returns a vector<string> and you give one of these strings to setX() and setY(), but both expect an integer parameter. You must convert the string to int
int x = atoi(fileDataAfterFiltered[1].c_str());
point2DObj[point2DCount].setX(x);
int y = atoi(fileDataAfterFiltered[2].c_str());
point2DObj[point2DCount].setY(y);
But: in C++ array and vector elements start at 0 not 1, so you might want to replace this with fileDataAfterFiltered[0] and fileDataAfterFiltered[1] respectively.
If you are using a C++11 compiler, function std::stoi() will do the trick:
point2DObj[point2DCount].setX(std::stoi(fileDataAfterFiltered[1]));
Otherwise you can use the old atoi():
point2DObj[point2DCount].setX(atoi(fileDataAfterFiltered[1].c_str()));
Aside from this, your code has many other problems, but I hope you can fix them by yourself.
there's plenty of ways of converting string to int. boost::lexical_cast is one which will magically do the conversion you want. Otherwise you can use atoi (if you don't care about errors), or strtol (if you do).
point2DObj[point2DCount].setX(atoi(fileDataAfterFiltered[1].c_str()));
point2DObj[point2DCount].setX(boost::lexical_cast<int>(fileDataAfterFiltered[1]));

Why does this combination of strtol and strtok not work?

Could anyone tell me what is wrong with this code?
for(int i=0;i<4;i++)
{
long int a = strtol(strtok("1-2-3-4","-"),(char**)NULL,10);
cout << a <<endl
}
I'm running on Solaris Unix. It's giving me a segmentation fault.
The fault is in strtol().
The error is with the strtok call, not with strtol. You can't call strtok on a string literal, since it's going to try to modify the string. Modifying a string literal causes undefined behaviour in C++.
The problems are legion.
I would expect that the core dump is because the string "1-2-3-4" is stored in read-only memory, so when strtok() modifies it (to isolate the first token), the program crashes. You say the crash is in strtol(); that would suggest that the return value from strtok() is NULL.
The first call to strtok() uses the string as an argument; the second call passes NULL in its place to indicate 'continue where you left off last time'. As written, if the string was modifiable, then you'd parse 1 four times.
This is closer to correct (though untested):
char input[] = "1-2-3-4";
char *data = input;
for (int i = 0; i < 4; i++)
{
char *token = strtok(data, "-");
if (token != 0)
{
long int a = strtol(token, NULL, 10);
cout << a << endl;
}
data = NULL;
}
In general, you need to do error detection from strtol(); further, doing so is quite fraught. However, with the sample string, you would not have to worry about that.
As the problem is already discussed, I'd like to show an alternate approach :
#include <stdio.h>
#include <string.h>
int main ()
{
long int a;
char str[] ="1-2-3-4";
char * pch;
pch = strtok (str,"-");
while (pch != NULL)
{
a = strtol(pch,(char**)NULL,10);
cout << a <<endl;
pch = strtok (NULL, "-");
}
return 0;
}