Here, I am basically trying to input a string, break it into individual words and assign each word to a char pointer ptr[i].On executing the following code, if I input string of more than one word, it shows Segmentation fault (core dumped). I used gdb for debugging. But after I visit while loop 2nd time, it showed Program received signal SIGSEGV, Segmentation fault.
0x0000003b64a81321 in __strlen_sse2 () from /lib64/libc.so.6
The solution for it is to allocate memory to each ptr[i] before strcpy(ptr[i],cp); using ptr[i]=new char[sizeof(cp)];. But, how is it that no memory allocation needed for ptr[0]? If I don't allocate memory to ptr[0], are there any chances of something else being overwritten? I am asking it out of curiosity, I know its always better to allocate memory. Here is the code:
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int main()
{
int i,j;
string s1;
getline(cin,s1);
char s[100],*ptr[10];
strcpy(s,s1.c_str());
char *cp;
cout<<"string is: "<<s1<<endl;
cp=strtok(s," ");
i=0;
while(cp!=NULL)
{ cout<<cp<<endl;
strcpy(ptr[i],cp);
cp=strtok(NULL," ");
i++;
}
for(j=0;j<i;j++)
{ cout<<ptr[j]<<endl;
}
return 0;
}
When you declare a local variable, it's contents is undefined. So when you declare an array of pointers, the pointers in the array will be pointing to seemingly random locations. Using an uninitialized pointer is undefined behavior. Undefined behavior may lead to a crash, or it may seemingly work, but you can't say beforehand what will happen.
There are two solutions to your problem:
Allocate memory for ptr[i] (even when i is zero).
Assign the pointer cp to ptr[i] instead.
Splitting a string on space can be done much more simpler in C++ than what you have though, see for example the following simple program:
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
int main()
{
// Put a string into a string stream
std::istringstream is("hello world how are you today");
// Vector where to store the "words"
std::vector<std::string> words;
// Now split the string on space
std::copy(std::istream_iterator<std::string>(is),
std::istream_iterator<std::string>(),
std::back_inserter(words));
// And finally print the words
for (const auto& word : words)
std::cout << word << '\n';
}
The output from this is:
hello
world
how
are
you
today
Here's a list of references for the used functions/classes:
std::istringstream
std::vector
std::copy
std::istream_iterator
std::back_inserter
Segmentation Fault occurs when you try to access that part of memory that your program is no allowed to. When you do
char *p[10];
it defines an array of 10 pointers. The content of array is unknown. Hence it could be memory location outside your program's. Possibly the 0th index has some value that is part your program's address space and hence it didn't complain. 2nd index had something that is not part your address space.
So, the behaviour is undefined. It totally depends on the content of array
Sometimes we may get no segmentation fault while using ptr[0], but this may not be the case always. And it is always better to allocate memory to the pointer before assigning any values to the object to which it is pointing.
Actually segmentation fault occurs due to the line :
strcpy(ptr[i],cp);
If you allocate some memory to ptr[i] with either new or malloc and then copy it should not sump.
Related
This question already has answers here:
Why don't I get a segmentation fault when I write beyond the end of an array?
(4 answers)
Closed 1 year ago.
if I don't define the size of my vector the segmentation fault will occur but in this way , I mean that I define the size lower than the size I use , the segmentation fault won't occur . but why?
what is the difference between them ?
#include <iostream>
#include <string>
using namespace std;
#include <vector>
int main()
{
vector <string> a(2);
a[0]="hello world";
a[2]="maryam";
cout << a[0] << a[2];
return 0;
}
C++ has a notion of undefined behavior. Accessing a vector out-of-bounds is a typical example of undefined behavior (because vector::operator[] performs no bounds checking). Nothing meaningful can be said about the outcome of the program.
But to explain what probably happens...
A vector is a class that usually contains a pointer to a heap-allocated array and its size (the "capacity").
An empty vector has a null pointer value. Dereferencing a null pointer often immediately leads to a segfault because there's no virtual memory region allocated at address 0.
On the other hand, a vector of capacity 2 points to an array of size 2. Writing past it is often possible, you will simply overwrite heap memory that happens to reside immediately after that array. This is called a heap buffer overflow. In a simple program it may appear to work fine. But in a larger program nothing good will happen somewhere further down the code.
Undefined behaviour (which is what you're doing when reading or writing beyond the end of a vector with operator[]) is exactly that, undefined.
It could just as easily crash for the size two case and seem to work for size zero.
Or both could format your storage devices while playing maniacal_laughter.mp3.
Undefined behaviour places no limits on the outcome, and it's something you would be well advised to steer clear of.
[] operator does not have range check. [] operator is used for directly accessing a memory address based on the offset value and "base" address.
From your example,
a[0], a[2]
0 and 2 are offset values, and "base" address will be the address of the array, pointed by the vector.
If you want to have range check, use:
a.at(0), a.at(2)
Below c++ program works fine, even though i have not allocated any memory to chr.
I went through google, SO and came across this
Why does this intentionally incorrect use of strcpy not fail horribly?
Here the program works fine for destination which has space less than the source.
Does that apply in my case also,strcpy writes into a random location in the heap?
#include<iostream>
using namespace std;
class Mystring
{
char *chr;
int a;
public:
Mystring(){}
Mystring(char *str,int i);
void Display();
};
Mystring::Mystring(char *str, int i)
{
strcpy(chr,str);
a = i;
}
void Mystring::Display()
{
cout<<chr<<endl;
cout<<a<<endl;
}
int main()
{
Mystring a("Hello world",10);
a.Display();
return 0;
}
output:-
Hello world
10
I tried the same thing with another c++ program, with any class and class member, and i was able to see the crash.
#include<iostream>
using namespace std;
int main()
{
char *src = "Hello world";
char *dst;
strcpy(dst,src);
cout<<dst<<endl;
return 0;
}
Please help me understand the behavior in the first c++ program.Is memory allocated somehow or strcpy is writing to some random memory location.
The behavior of your program is undefined by the C++ standard.
This means that any C++ implementation (e.g. a compiler) can do whatever it wants. Printing "hello!" on stdout would be a possible outcome. Formatting the hard disk would still be acceptable, as far as the C++ standard is involved. Practically, though, some random memory on the heap will be overwritten, with unpredictable consequences.
Note that the program is even allowed to behave as expected. For now. Unless it's Friday. Or until you modify something completely unrelated. This is what happened in your case, and is one of the worst thing to happen from the point of view of a programmer.
Later on, you may add some code and see your program crash horribly, and think the problem lies in the code you just added. This can cause you to spend a long time debugging the wrong part of the code. If that ever happens, welcome to hell.
Because of this, you should never, ever, rely on undefined behavior.
strcpy() is indeed writing to a random location.
And it's a blind luck if your program runs fine and nothing crashes.
You have created on object of MyString class on a stack. In that object there's a member pointer chr, which points to some arbitrary location. Does your constructor take care to initialize that pointer or allocate a memory for the pointer to point at? -- No, it doesn't. So chr points somewhere.
strcpy() in its turn doesn't care about any pointer validity, it trusts your professionalism to provide valid input. So it does its job copying stings. Luckily, overwriting memory at the location pointed by an uninitialized chr doesn't crash you program, but that's "luckily" only.
It is known that strcpy() can cause overflow errors, because there is no check made wherever the data will fit in the new array or not.
The outcome of this overflow may sometime never been noticed, it all depends on where the data is written. However a common outcome is heap and/or program corruption.
A safe alternative of strcpy() is the usage of strcpy_s() that requires also the size of the array. You can read more about the usage of strcpy_s() on MSDN or here
Actually, strcpy() does something like this:
char *strcpy(char *dest, const char *src)
{
unsigned i;
for (i=0; src[i] != '\0'; ++i)
dest[i] = src[i];
dest[i] = '\0';
return dest;
}
So, when you pass a pointer to some character array to strcpy, it copies data from src to dest until it reaches NULL terminated character.
Character pointer does not contain any information about length of string, so when you pass dest pointer, it copies data even though you haven't assigned memory to it.
Run this example code, you will get my point:
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
char str1[] = "Hello_World!";
char str2[5];
char str3[10];
strcpy(str2,str1);
cout << "string 1:" << str1 << endl;
cout << "string 2:" << str2 << endl;
cout << "string 3:" << str3 << endl;
return 0;
}
This will not show any error but you can understand by my example that this is not a good practice.
This below gives me 'Segmentation fault (core dumped)' error after printing the reversed string. Can anyone explain why ?
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
void print (char *str) {
if (*str) {
print (str+1);
cout << *str;
}
}
int main() {
char *str;
cin >> str;
print(str);
cout << endl;
return 0;
}
Uninitialized non-static local variables have an indeterminate value, and will in reality be seemingly random. Using them without initialization leads to undefined behavior, which is one of the most common causes of crashes.
The problem is that you have a pointer, but it doesn't point anywhere so when you use it to read input, the input stream cin will write to a random location in memory.
The solution is to not use character pointers for string, but the std::string class.
If you have to use pointers, then you have two solutions: Either declare the string as an array, or allocate memory using the new operator. However be cautioned that if you input more than you have allocated you will write out of bounds and once again have undefined behavior.
You have not allocated any memory to char *str. Try using char str[20] (20 is just an example, it could be anything as per your demand and your machine's capability) and everything will be fine. You are assuming that compiler will allocate memory for you but that's not the case. You are trying to access an unallocated memory or you can dynamically allocate them using malloc or new.
More than that you can use std::string to do get help from stl.
Either declare the str like char str[fixed_size] or use std::string. One of the simplest methods to do that might be this:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str;
cin >> str;
reverse(str.begin(),str.end());
cout <<str<< endl;
return 0;
}
I am working on this assignment and have encountered a problem. At one point, I have to ask the user for two input commands to be used later and I want them put in a char array. I then want to put the input they have into char* but I end up with a Segmentation fault
Here is a small part of my code that shows where I'm having problems:
#include <iostream>
#include <cstring>
using namespace std;
int main(){
char firstAns[80];
char * command1[5];
int ansLen;
//Ask for command
cout << "Please enter your first command(incl. args) or quit: ";
cin >> firstAns;
ansLen = strlen(firstAns);
for(int i=0; i < ansLen; i++){
strcpy(command1[i], firstAns);
}
The program that I ran this from compiles just fine but I have narrowed the segmentation fault to this part of the program and could use some help as a novice programmer :)
You have an array of char* called command. But you haven't allocated any memory for the pointers in the array, or even set them to null. SO they're random values, pointing to random memory locations. Strcpy is then overwriting those random locations, causing a seg fault. You need to allocate memory for those pointers by command[i]=new char[80] on all 5 rows first.
char * command1[5];
This is an array of char*s. However, it is uninitialized - the values can be any value, and as such they point to random, meaningless places in memory.
You then later use the uninitialized command1[i] in strcpy(command1[i], firstAns);. Essentially, what you have done is taken a random place in memory and tried to copy firstAns to it. No wonder your program crashes!
Before using a pointer, you have to initialize it to some value. If you need storage in memory, use malloc() to return storage of the correct size (sizeof(datatype)*length +1 if it is a string) and remember to free() the pointer returned from it when you're done with it.
Read more: http://www.cplusplus.com/reference/cstdlib/malloc/
(Gabe Sechan's solution is also valid. new and malloc are the C++ and C ways of allocating memory)
Additional Problem is here:
ansLen = strlen(firstAns);
for(int i=0; i < ansLen; i++){
strcpy(command1[i], firstAns);
}
ansLen is the length of firstAns, it may be possible that it is longer than 5. In this case,
if you try to access command1[i], you are going to access memory that out of bounds, results in segfault.
Meanwhile, you are using unitialized command1 as pointed out by Patashu and Gabe.
I have the following program:
//simple array memory test.
#include <iostream>
using namespace std;
void someFunc(float*, int, int);
int main() {
int convert = 2;
float *arr = new float[17];
for(int i = 0; i < 17; i++) {
arr[i] = 1.0;
}
someFunc(arr, 17, convert);
for(int i = 0; i < 17; i++) {
cout << arr[i] << endl;
}
return 0;
}
void someFunc(float *arr, int num, int flag) {
if(flag) {
delete []arr;
}
}
When I put the following into gdb and insert a break point at float *arr ..., I step through the program and observe the following:
Printing the array arr after it has been initialized gives me 1 17 times.
Inside someFunc too, I print arr before delete to get the same print as above.
Upon going back into main, when I print arr, I get the first digit as 0 followed by 16 1.0s.
My questions:
1. Once the array has been deleted in someFunc, how am I still able to access arr without a segfault in someFunc or main?
2. The code snippet above is a test version of another piece of code that runs in a bigger program. I observe the same behaviour in both places (first digit is 0 but all others are the same. If this is some unexplained memory error, how am I observing the same thing in different areas?
3. Some explanations to fill the gaps in my understanding are most welcome.
A segfault occurs when you access a memory address that isn't mapped into the process. Calling delete [] releases memory back to the memory allocator, but usually not to the OS.
The contents of the memory after calling delete [] are an implementation detail that varies across compilers, libraries, OSes and especially debug-vs-release builds. Debug memory allocators, for instance, will often fill the memory with some tell-tale signature like 0xdeadbeef.
Dereferencing a pointer after it has been deleteed is undefined behavior, which means that anything can happen.
Once the array has been deleted, any access to it is undefined behavior.
There's no guarantee that you'll get a segment violation; in fact,
typically you won't. But there's no guarantee of what you will get; in
larger programs, modifying the contents of the array could easily result
in memory corruption elsewhere.
delete gives the memory back to the OS memory manager, but does not necessarily clears the contents in the memory(it should not, as it causes overhead for nothing). So the values are retained in the memory. And in your case, you are accessing the same memory -- so it will print what is in the memory -- it is not necessarily an undefined behaviour(depends on memory manager)
Re 1: You can't. If you want to access arr later, don't delete it.
C++ doesn't check for array boundaries. Only if you access a memory which you are not allowed to you will get segfault