C++ Segmentation Fault in a While Loop - c++

I have a loop like this:
while (k < wordnum) { // wordnum is 9 in my case
/*There is a text file that includes some words
*Starting positions of words are kept in wordIndexes
*Don't worry about not having indexes*/
//std::ifstream s_words
s_words.seekg(*(wordIndexes + k) + 1, s_words.beg);
char *p_Word = new char[16];
s_words.getline(p_Word,15,'\n');
//After getting word, they are copied in a struct
word.id = wordnum - k;
word.word = new char [strlen(p_Word)];
strcpy(word.word,p_Word);
word.wordLength = strlen(p_Word);
delete[] p_Word;
//At last, the word is sent for search
if (verticalSearch(puzzleArray, &word)){
k++;
cout<<"Found vertically"<<endl;
delete[] word.word;
}
else if (horizontalSearch(puzzleArray, &word)){
k++;
cout<<"Found horizontally"<<endl;
delete[] word.word;
}
else if (diagonalSearch(puzzleArray, &word)){
k++;
cout<<"Found Diagon Alley"<<endl;
delete[] word.word;
}
else{
k++;
delete[] word.word;
}
}
I know this is not a well designed code but that's not it. While loop and functions work perfectly until the last loop. When the last loop finishes, instead of getting out of the loop, program gives segmentation error. I'm sure that last word is not causing that because it is found in a right way and returned true. Also I'm sure that none of the words more than 15 characters. At the very last, k++ is working and k becomes 9. Then error comes. I'm using linux so I tried to find where is the problem with gdb and I got this:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7534467 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
I don't know what that means. Do this information help me or should I try something else?
p.s: The program working smoothly in windows.

word.word = new char [strlen(p_Word)];
strcpy(word.word,p_Word);
You didn't allocate enough space for word.word. A string with a string length of 15 characters requires 16 characters to store because C-style strings have a nul terminator to mark their end.
The effect of overwriting the bounds of an allocated memory block are unpredictable and can differ on different platforms.
You are making things extra difficult by not using any of the numerous C++ features that make life simpler and by not having any test coverage. For example, if you had a "string duplicate" function to duplicate the string and had test coverage for that function, you would probably have localized this problem yourself.

Related

How to interpret a GDB backtrace in order to determine a segmentation fault?

I am in an entry level programming class. I understand that segmentation faults are due to an error in memory storage somewhere along the way. The program I wrote is supposed to take a file given to us that is in code and contains the instructions to decode it and then print the decoded message.
We have several test cases and my code runs for some of them, but not for the last one. I learned about GDB for debugging for the first time today and used backtrace full to try and source the error, but I'm not totally sure how to interpret what it gave me.
This is the code that I wrote.
**edited code out
When I did a backtrace, this is what it told me.
#2 0x0000000000401523 in main () at main.cpp:42
second = 61 '='
third = 72 'H'
msg = 0x606308
i = 8
chars = ""
first = 90 'Z'
numMess = 8
out = <incomplete type>
name = "input4.txt"
in = <incomplete type>
arr = "IJKLMNOPQRSTUVWXYZABCDEFGH"
I don't know what the backtrace is telling me and I'm unsure of what to do with that information to discover and fix my error.
The hints from the trace are
i = 8
chars = ""
numMess = 8
i equals numMess and chars is empty.
Why does this matter? Looking at where numMess comes from, we see it's used to size the dynamic array pointed at by msg and msg is later indexed by i. when i equals numMess, msg[i] is out of bounds.
So how did this happen?
string chars;
getline(in, chars); // this doesn't make much sense. Reconsider it
for (chars; std::getline(in, chars); i < numMess) {
Here's where things went wrong. A for loop should look something like
for (initializer ; exit condition ; iterator to advance the loop)
but
for (chars; // does nothing. Compiler may be warning you
std::getline(in, chars); // loop exits on failed read
i < numMess) { // does nothing to advance the loop
Nothing in here prevents i from exceeding numMess because i < numMess is not being used as an exit condition. Right, but why doesn't std::getline(in, chars); kick out of the loop when it hits the end of the file? Empty line at the end of the file. chars was successfully set to an empty string.
for ( ; // nothing happening here
i < numMess and std::getline(in, chars) ;
++i) { // and remove the ++i from the end of the loop.
Gets you out of the current predicament and might give you a program that does what you want. Haven't tested it.
But what if there is a mistake in the file and the file exits before reaching numMess? This is the sort of stuff PaulMckenzie is getting at. You're better off not trusting numMess at all and going with something more like
int numMess = 0;
in >> numMess; // not that we care
vector<Messages> msg;
//read file
int i = 0;
string chars;
while (std::getline(in, chars)) { // get each line. Note this gets the empty line, too
Messages temp; // make a temporary for storage
temp.messageNum = i + 1;
temp.codedMessage = chars;
//decode file
for (char &j : chars) {
if (j - 'A' >= 0 && j - 'A' < 26)
j = arr[j - 'A'];
}
temp.decodedMessage = chars;
msg.push_back(temp);
}

C++ Dynamic bool array causes crash

Today I tried to program the Sieve of Eratosthenes and it works as far as it provides me with the prime numbers. But I have a problem with the dynamic array I don't understand.
First problem: As soon as I try to enter a "big" value for n (for example 120), the program crashes, it doesn't even allocate the memory.
Second problem: If I enter a value like 50 it is able to give out the correct prime numbers but crashes before it deletes the array.
Third problem: If I enter a very small value like 5 it is able to execute the entire program, it gives out the correct numbers and deletes the memory.
But I don't understand why it acts so differently. 120 boolean values can't crash my memory, at least I think so. And why isn't it able to delete an array of 50 values but is actually able to delete an array of 5 values?
Can anyone tell me what's the problem?
int n;
cin >> n;
n=n+1;
bool *feld = new bool[n];
for(int i=2;i<n;i++)
{
int j=i*i;
feld[j]=true;
for(;j<n;j+=i)
feld[j]=true;
}
for(int i=2;i<n;i++)
if(!feld[i])
cout << i << endl;
else;
delete[] feld;
feld = NULL;
Your problem is here:
int j=i*i;
feld[j]=true;
there is no check as to whether j < n so you are stomping over unallocated memory when j >= n.
This code is wrong
bool *feld = new bool[n];
for(int i=2;i<n;i++)
{
int j=i*i;
feld[j]=true;
...
}
Suppose n == 10 and i == 9, then j == 81 but you only have 10 elements in your bool array.
This is how it works when you write bugged programs, sometimes it seems to work, it might even give the right answer, other times it will crash. This is a very important lesson, and you're actually lucky to have learned it early.
Actually It's not just that feld[j]=true; is causing the error.
Also, you don't need that line at all before the loop.
because, it's the first case inside the loop.

Segmentation fault : Address out of bounds for a pointer in C

I am trying to build and run some complicated code that was written by someone else, I don't know who they are and can't ask them to help. The code reads a bpf (brain potential file) and converts it to a readable ascii format. It has 3 C files, and 2 corresponding header files. I got it to build successfully with minor changes, however now it crashes
with a segmentation fault.
I narrowed the problem down to FindSectionEnd() (in ReadBPFHeader.c) and find that the error occurs when sscanfLine() (in the file sscanfLine.c) is called (code for both is below).
ui1 is defined as unsigned char.
si1 is defined as char.
Just before returning from sscanfLine(), the address pointed to by dp is 0x7e5191, or something similar ending with 191. However, on returning to FindSectionEnd(), dp points to 0x20303035 and it says 'Address 0x20303035 is out of bounds', which then causes a fault at strstr(). The loop in FindSectionEnd() runs without problem for 14 iterations before the fault occurs. I have no idea what is going wrong. I really hope the information I have given here is adequate.
ui1 *FindSectionEnd(ui1 *dp)
{
si1 Line[256], String[256];
int cnt=0;
while (sscanfLine(dp, Line) != EOF){
dp = (ui1 *)strstr(dp, Line);
dp+= strlen(Line);
sscanf(Line,"%s",String);
if(SectionEnd(String))
return(dp);
}
return(NULL);
}
si1 *sscanfLine(ui1 *dp, si1 *s)
{
int i = 0;
*s = NULL;
int cnt = 0;
while (sscanf(dp, "%c", s + i) != EOF){
cnt++;
dp++;
if(*(s + i) == '\n') {
*(s + i + 1) = '\0';
return s;
}
++i;
}
*(s + i) = '\0';
return s;
}
The sscanfLine function doesn't respect the size of the buffer passed in, and if it doesn't find '\n' within the first 256 bytes, happily trashes the stack next to the Line array.
You may be able to work around this by making Line bigger.
If you're going to improve the code, you should pass the buffer size to sscanfLine and make it stop when the count is reached even if a newline wasn't found. While you're at it, instead of returning s, which the caller already has, make sscanfLine return the new value of dp, which will save the caller from needing to use strstr and strlen.
My first guess would be that your string is not null terminated and strstr() segfaults because it reads past the boundaries of the array

Debug Assertion Failed! String manipulation using pointer arithmetic

EDIT: Pastebin links to the entirety of the code at the bottom
for my CS215 course, I was given a class called String215 which is a basic string class to help in the understanding of dynamic memory allocation and pointer arithmetic with char arrays.
The class was given to me in a very basic skeleton form with prototypes but no implementations, along with a test function to test my implementations. I CAN NOT use any C String functions in this assignment.
The part of the program which is troubling is the append function, which just appends a parameter string215 object to the end of the current string215 object.
// Add a suffix to the end of this string. Allocates and frees memory.
void string215::append(const string215 &suffix)
{
char *output = new char[str_len(data)+suffix.length()+1];
for(int x = 0; x < str_len(data); x++) {
*output = *data;
output++;
data++;
}
for(int x = 0; x < suffix.length(); x++) {
*output = suffix.getchar(x);
output++;
}
*output = '\0';
output -= (str_len(data)+suffix.length()+1);
delete[] data;
data = output;
}
This portion of the code is tested in the 13th test of the test function as shown here:
string215 str("testing");
...
// Test 13: test that append works in a simple case.
curr_test++;
string215 suffix("123");
str.append(suffix);
if (strcmp(str.c_str(), "testing123") != 0) {
cerr << "Test " << curr_test << " failed." << endl;
failed++;
}
Here is the description of the append class:
Add the suffix to the end of this string. Allocates a new, larger, array; copies the old contents, followed by the suffix, to the new array; then frees the old array and updates the pointer to the new one.
My program aborts at the very end of the append function execution with the error message:
Debug Assertion Failed!
Program: [Source path]\dbgdel.cpp
Line: 52
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
...
Abort || Retry || Ignore
I'm fairly certain it has something to do with my very poor memory management. I know it's not a lot to go on, but I've been struggling with this for hours on end and can't seem to figure it out.
Here's a pastebin of the .cpp and .h file for this program
string215.cpp: http://pastebin.com/Xh2SvDKJ
string215.h: http://pastebin.com/JfAJDEVN
Any help at all is greatly appreciated!
Thanks,
RAW-BERRY
You are changing data pointer before delete[]. You need to delete[] exactly the same value you got from new[].
Also, you are incrementing output pointer str_len(data)+suffix.length() times, and you take it back by str_len(data) + suffix.length() + 1.
I would use separate variables for iteration to solve these problems.
You increment output exactly str_len(data) + suffix.length() times. Note that you don't increment output after *output = '\0';.
So to go back to the start, you should use:
output -= (str_len(data) + suffix.length());
By the way, some of the code is not very efficient. For example, getchar uses a loop instead of simply returning data[index]. You use getchar in append, which means that the performance isn't great.
EDIT: As zch says, you use delete[] data after modifying data, but note that even before that you use str_len(data) after modifying data (when deciding how many bytes to go skip back), so the calculation is wrong (and my suggestion above is also wrong, because str_len(data) is now zero).
So I think your problem is with the line
for(int x = 0; x < str_len(data); x++) {
Notice that the size of 'data' is changing at each iteration of the loop. As you increment 'x', you are decreasing the length of 'data'. Suppose 'data' is a string holding "hello": in the first iteration of the loop x=0 and str_len(data)=5; in the second iteration x=1 and str_len(data)=4. Thus the for loop executes half as many times as you need it to and 'data' does not end up pointing to the end of the data string

Why does string.insert(iterator,char) work six times in a row but not seven? (C++)

Code:
#include <iostream>
#include <string>
using namespace std;
string expand(string mask);
int main()
{
string tiny = "blah blah [a-e] blah blah";
string lengthy = "blah blah [a-i] blah blah";
cout << expand(tiny) << endl;
cout << expand(lengthy) << endl;
return 0;
}
string expand(string mask)
{
int i, range;
/* find the first bracket, grab start letter */
unsigned int bracket = mask.find("[");
char start = mask[bracket + 1];
/* point iterator at first bracket */
string::iterator here = mask.begin();
here += bracket;
/* find second bracket, calculate ascii range */
range = mask[bracket + 3] - mask[bracket + 1];
/* kill brackets and their contents*/
mask.erase(here, here + 5);
/*** This loop causes an error on the 7th iteration ****/
for(i = 0; i <= range; i++)
mask.insert(here, (start + range) - i);
return mask;
}
Output:
matt#Callandor:~/prog/tempVer$ g++
test.cpp -o play
matt#Callandor:~/prog/tempVer$ ./play
blah blah abcde blah blah
���blah blah defghi blah blah
* glibc detected * ./play: free(): invalid next size (fast): 0x08353068
======= Backtrace: ========= /lib/libc.so.6(+0x6c501)[0x5b5501]...
I am running into some odd behavior when trying to use string::insert(iterator,char); I have it inside a 'for' loop where I don't move the iterator at all, the loop just inserts characters. It works fine if I have six or fewer characters to insert, but fails for seven or more.
Based on the output (see above) it looks like after six insertions the iterator jumps to the beginning of the string and begins inserting garbage. When the program finishes I get a large messy error.
While trying to isolate the cause I tried two loops (none of which touch the iterator):
for(i = 0; i < 6; i++)
mask.insert(here, (start + range) - i);
cout << mask << endl;
for(i = 0; i < 7; i++)
mask.insert(here, (start + range) - i);
cout << mask << endl;
The first completed just fine, the second caused a segmentation fault.
Anybody know what is going on here?
After pouring over your code, I noticed that you are using an invalidated iterator.
In a nutshell, insertion into a string invalidates its iterators. After your insert, the here iterator is no longer valid, because, among other implementation specific details, the string capacity could have increased. This leads to undefined behavior when the here iterator is used again after the insert, without first being reset to a valid spot in the modified string.
Probably because when the string has to resize, the internal string will be at a different location in memory and your iterator, here, becomes invalid.
std::basic_string<T>::insert invalidates ALL iterators. Therefore here is not valid after the insert call. Therefore the program has undefined behavior and is allowed to format your hard disk if it want's to :)
Seriously though, you want here = mask.insert(here, (start + range) - i); as the body of that for loop.
Oh, and you should probably make sure the find operation succeeds before proceeding :)
EDIT: You're probably better off refactoring this into something which builds a string containing what you want to add, then running a single insert, rather than running n inserts, because n inserts results in an algorithm with potentially quadratic time.
I'm not quite sure I'm qualified to give you advice here, but it sure smells like you're indexing past the end of the array.
The questioner asked why it worked for 6 and not for 7.
The other posters have come close by answering the second part, so I will clarify that insert may invalidate your iterators, but will not necessarily.
If insert has to reallocate memory then it will invalidate iterators. If it does not have to reallocate memory the iterators might not become invalidated.
You were therefore "lucky" the first 6 times but finally got caught.
You are also erasing 5 elements so that might invalidate your iterators, however in this case your iterator is probably just implemented as a pointer or a light wrapper to one, so again you "got away with it".
You should not normally rely on getting away with it, but in the case you first call reserve() and then you just do push_back() calls, you can be certain your iterators will not be invalidated until you pass the capacity you have reserved.