Unclear Segmentation fault of using Boost Coroutine(1.55)? - c++

I write a piece of code which will get a Segmentation fault. I am not sure whether it is a bug of Boost Coroutine or my code below:
#include <string>
#include <functional>
#include <vector>
#include <fstream>
#include <boost/coroutine/coroutine.hpp>
using namespace std;
template <class T>
using C = boost::coroutines::coroutine<T()>;
string foo(C<string>::caller_type & yield,
std::string fn, int cnt) {
std::ifstream f(fn);
// f.close();
int local_cnt = 0;
while(local_cnt < cnt) {
string l;
getline(f, l);
local_cnt ++;
yield(l);
}
f.close();
}
int main(int argc, char *argv[])
{
vector<C<string> > result;
for(int i = 0; i < 8192; ++i) {
C<string> obj(bind(foo, std::placeholders::_1, "test.txt", 3)); // line I
result.push_back(std::move(obj)); // line J
}
return 0;
}
test.txt is very large so it will never get the eof before segfault occurring. I use 1.55 of Boost and there are some observation:
seg-error occured in line I
If I delete or move f.close() before yield clause, seg-error disappeared.
If I delete line J in the code, seg-error disappeared.
If I use a smaller number in stead of 8192(say 512), seg-error disappeared.
What's the problem here?

"Too many open files" - you exceed the max number of open file descriptors
If I use a smaller number in stead of 8192(say 512), seg-error disappeared.
the seg fault will happen inside the ifstream (does not throw)
check ulimit -n
cat /proc/sys/fs/file-max
sysctl

Related

Why do I keep getting a zsh: segmentation fault error when I use a.out for this file?

New to file io in c++. I'm initially writing a basic program to simply remove comments from a file. If the first two characters are //, then I basically need to skip and print the following line in the text file. My output file and input file are both in the same folder as my CPP file, so I'm not sure why I keep getting an error here.
#include <iostream>
#include <stream>
using namespace std;
int main() {
ifstream in_stream("HW2Test.txt");
ofstream output_stream("HW2output.txt");
string result[100];
int i;
while(!in_stream.eof()) {
in_stream>>result[i];
i++;
}
for(int j = 0; j<i; j++) {
if((result[j][0]=='/')&&(result[j][0]=='/')) {
output_stream<<result[j+1];
}
}
output_stream.close();
in_stream.close();
return 0;
}
Your variable int i is not initialized, so in_stream>>result[i] yields undefined behaviour.
Use int i=0 instead (and check if i < 100 before writing to your buffer).

Stack overflow with no recursion?

As far as I can see, my code has no recursion, but I am getting exception 0xC00000FD. According to Rider For Unreal Engine, it is happening in the main function. It's being encountered at the decompiled code
mov byte ptr [r11], 0x0
It was working fine, then suddenly when I ran it a second time, just to make sure it worked, it broke. It now gives that exception every time.
Here is my code:
// Language.cpp
#include <fstream>
#include <iostream>
#include <regex>
#include <stdexcept>
#include <string>
#include "Lexer/Lexer.h"
#include "Util/StrUtil.h"
int main(int argc, char* argv[])
{
std::string line, fileString;
std::ifstream file;
file.open(argv[1]);
if(file.is_open())
{
int lines = 0;
while(file.good())
{
if (lines > 10000)
{
std::cerr << "Whoa there, that file's a little long! Try compiling something less than 10,000 lines." << '\n';
return -1;
}
getline(file, line);
fileString += line + (char)10;
lines++;
}
}
fileString += (char)0x00;
std::string arr[10000];
int arrLength = StrUtil::split(fileString, "\n", arr);
Line lines[10000];
Lexer::lex(arr, arrLength, lines);
return 0;
}
// Lexer.cpp
#include "Lexer.h"
void Lexer::lex(std::string (&str)[10000], int length, Line (&lines)[10000])
{
for (int i = 0; i < length; i++)
{
}
}
// StrUtil.cpp
#include "StrUtil.h"
#include <stdexcept>
#include <string>
int StrUtil::split(std::string str, std::string delimiter, std::string (&out)[10000])
{
int pos = 0;
out[0] = str;
while (out[pos].find(delimiter) != std::string::npos)
{
const size_t found = out[pos].find(delimiter);
out[pos + 1] = out[pos].substr(found + delimiter.length());
out[pos] = out[pos].substr(0, found);
pos++;
}
return pos + 2;
}
For custom types, Line is an array of Tokens, which are just <TokenType, std::string> pairs.
As far as I can see, my code has no recursion
Indeed, there is no recursion in the shown code. Lack of recursion doesn't mean that you won't overflow the stack.
Stack overflow with no recursion?
Yes, this program is likely going to overflow the stack on some systems.
std::string arr[10000];
Typical size of std::string is 32 bytes (can vary greatly between language implementations). 10000 strings is 312 kiB. The execution stack on most desktop systems is one to few MiB. That one array is about the third of the memory that has to fit all of the automatic variables at the deepest stack frame of the program. It is very feasible that the remaning stack memory isn't enough for the rest of the program, especially considering you have another huge array of Line objects.
To fix the program, do not allocate massive variables such as this in automatic storage.

Searching for an int inside a file

So I am supposed to take all ints in source3.txt and check which of them occur in source.txt. If any of them don't occur, I'm supposed to print a corresponding line from source2.txt to output.txt (source2.txt contains descriptions of the numbers in source 3, in the same order, each description is 1 line). I wrote this code, but it only prints the last line from source2.txt, furthermore it is a wrong line.
I have no idea what might be wrong. Can you help me?
#include <bits/stdc++.h>
using namespace std;
int main()
{
ifstream source ("source.txt");
ifstream source2 ("source2.txt");
ifstream source3 ("source3.txt");
vector<int> tab(1051,0);
vector<string> tab2(857,*new string);
vector<int> tab3(857,0);
ofstream output("output.txt");
for(int i=0;i<1050;++i)
{
source>>tab[i];
}
for(int i=0;i<856;++i)
{
string a;
getline(source2,a);
tab2[i]=a;
source3>>tab3[i];
}
for(int i=0;i<856;++i)
{
if(std::find(tab.begin(), tab.end(), tab3[i]) != tab.end())
{
continue;
}
else
{
output<<tab2[i]<<endl;
}
}
}
I think below modifications to code should work for you . Replace value of SOURCE_COUNT with 1051 and SOURCE2_COUNT with 857
#include <iostream>
#include <fstream>
#include <vector>
#include <vector>
const int SOURCE_COUNT = 4;
const int SOURCE2_COUNT = 3;
//const int SOURCE2_COUNT = 3;
using namespace std;
int main()
{
ifstream source ("source.txt");
ifstream source2 ("source2.txt");
ifstream source3 ("source3.txt");
vector<int> tab(SOURCE_COUNT,0);
vector<string> tab2(SOURCE2_COUNT,"");
vector<int> tab3(SOURCE2_COUNT,0);
ofstream output("output.txt");
for(int i=0;i<SOURCE_COUNT;++i)
{
source>>tab[i];
}
for(int i=0;i<SOURCE2_COUNT;++i)
{
string a;
getline(source2,a);
tab2[i]=a;
source3>>tab3[i];
}
for(int i=0;i<SOURCE2_COUNT;++i)
{
if(std::find(tab.begin(), tab.end(), tab3[i]) != tab.end())
{
continue;
}
else
{
output<<tab2[i]<<endl;
}
}
}
It looks to me like you are printing only in those cases where you have not found the number. In other words, the cases in your if-statement are reversed. It should read:
if(std::find(tab.begin(), tab.end(), tab3[i]) != tab.end())
output<<tab2[i]<<endl;
[EDIT] Oops, I read the question not carefully enough. It should print the line, if the number is NOT contained in source3. So the loop should read:
if(std::find(tab.begin(), tab.end(), tab3[i]) == tab.end())
output<<tab2[i]<<endl;
Also: I would strongly suggest to do away with all those constants like 856 and 1050. Why don't you simply read the file until you reach the end?

delete in threads gives a segmentation fault

This program counts the occurrence of a word in a line. It runs as expected, but I have 2 concerns:
delete tmp is commented as of now (line 57). If it is uncommented and compiled, my executable gives "segmentation fault". Oddly, it doesn't crash while running in gdb nor with valgrind.
Lines 65 and 66: ideally these threads would need to be joined. But, I am getting correct output even though they are not joined. Is this how it behaves for a shared (volatile) variable?
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <fstream>
#include <new>
#define MAX_BUFF 1000
using namespace std;
volatile int tcount=0;
pthread_mutex_t myMux;
typedef struct data
{
string line;
string arg;
}tdata;
void *calcWordCount(void *arg)
{
tdata *tmp = (tdata *)arg;
string line = tmp->line;
string s = tmp->arg;
int startpos = 0;
int finds = 0;
while ((startpos = line.find(s, startpos)) != std::string::npos)
{
++finds;
startpos+=1;
pthread_mutex_lock(&myMux);
tcount++;
pthread_mutex_unlock(&myMux);
}
//cout<<endl<<line<<s<<" "<<finds<<endl;
}
int main(int argc,char *argv[])
{
pthread_t thread_ids[10000];
int cnt=1;
int thread_cnt=0;
void *exit_status;
int targc=argc;
ifstream infile("testfile");
string line;
while(getline(infile,line))
{
while(targc >1)
{
tdata *tmp = new tdata;
tmp->line = line;
tmp->arg = argv[cnt];
pthread_create(&thread_ids[thread_cnt],NULL,calcWordCount,tmp);
thread_cnt++;
cnt++;
targc--;
//delete tmp;
}
cnt=1;
targc=argc;
}
infile.close();
int j;
/*for(j=0;j<thread_cnt;j++)
pthread_join(thread_ids[j],&exit_status);*/
cout<<tcount<<endl;
return 0;
}
You have undefined behaviour as you're calling delete on tmp and another thread is consuming it.
One fix would be to create and pass (by value) a std::shared_ptr rather than the bare pointer into your worker thread. You can use release and reset methods in your main loop. The memory will be released by std::shared_ptr once the worker thread is done with it.

Segmentation Fault while Reading from File

I am trying to print last 10 lines of a file. Following is my code, but it is giving a segmentation fault due to fscanf. While running with gdb the fault reads : vfscanf.c: No such file or directory.
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
int main()
{
FILE *fp = fopen("microfile.txt","r");
char *c[10];
int idx = 0;
cout<<fp<<"\n";
while(!feof(fp))
{
if(idx<10)
{
fscanf(fp,"%s",c[idx]);
idx++;
}
else if(idx==10)
{
for(int i=0;i<idx-1;i++)
{
c[i] = c[i+1];
}
fscanf(fp,"%s",c[idx-1]);
}
}
int i=0;
while(i<10)
{
cout<<c[i]<<"\n";
i++;
}
}
The source of the problem comes from the fact you have an array of pointers on this line:
char* c[10];
And later on in the program you attempt to assign character values to these pointers. Maybe you meant for just an array of characters instead:
char c[10];
Moreover, use of the Standard library is recommended. Try using std::string and standard streams and your program can be made more maintainable:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::string s;
s.assign(
std::istreambuf_iterator<char>(std::ifsteam("microfile.txt").rdbuf()),
std::istreambuf_iterator<char>());
for (char c : s)
std::cout << c << std::endl;
}