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.
Related
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.
I am having what seems to be a common issue however reading through the replies to the similar questions I can't find the solution to my issue at all as I have already done what they are suggesting such as making the variable an array. I have the following code:
#include "stdafx.h"
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>
#include <future>
using namespace std;
string eng2Str[4] = { "money", "politics", "RT", "#"};
int resArr[4];
int main()
{
engine2(eng2Str[4], resArr[4]);
system("Pause");
system("cls");
return 0;
}
void engine2(string &eng2Str, int &resArr)
{
ifstream fin;
fin.open("sampleTweets.csv");
int fcount = 0;
string line;
for (int i = 0; i < 4; i++) {
while (getline(fin, line)) {
if (line.find(eng2Str[i]) != string::npos) {
++fcount;
}
}
resArr[i] = fcount;
}
fin.close();
return;
}
Before you mark as duplicate I have made sure of the following:
The array and variable I am trying to assign are both int
Its an array
The error is:
expression must have pointer-to-object type
The error is occurring at the "resArr[i] = fcount;" line and am not sure why as resArr is an int array and I am trying to assign it a value from another int variable. I am quite new to C++ so any help would be great as I am really stuck!
Thanks!
The problem is that you've declared your function to take a reference to a single string and int, not arrays. It should be:
void engine2(string *eng2Str, int *resArr)
or:
void engine2(string eng2Str[], int resArr[])
Then when you call it, you can give the array names as arguments:
engine2(eng2Str, resArr);
Another problem is the while loop in the function. This will read the entire file during the first iteration of the for() loop. Other iterations will not have anything to read, since it will be at the end of the file already. You could seek back to the beginning of the file, but a better way would be to rearrange the two loops so you just need to read the file once.
while (getline(fin, line)) {
for (int i = 0; i < 4; i++) {
if (line.find(eng2Str[i]) != string::npos) {
resArr[i]++;
}
}
}
I would suggest to use std::vector instead of pure C array.
In your code, there are more issues.
You are passing the fourth element of both arrays to the engine2 function.
From your definition of void engine2(string &eng2Str, int &resArr) you expect reference to a string (not array / vector) and an address / reference of int - you need to pass an pointer to the first element of resArr.
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <future>
using namespace std;
vector<string> eng2Str = { "money", "politics", "RT", "#" };
int resArr[4] = {};
void engine2(const vector<string>& eng2Str, int* resArr)
{
ifstream fin;
fin.open("sampleTweets.csv");
int fcount = 0;
string line;
for (int i = 0; i < 4; i++)
{
while (getline(fin, line))
{
if (line.find(eng2Str[i]) != string::npos)
{
++fcount;
}
}
resArr[i] = fcount;
}
fin.close();
return;
}
int main()
{
engine2(eng2Str, resArr);
system("Pause");
system("cls");
return 0;
}
I have this program:
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <sstream>
#include <algorithm>
int main(int argc, const char * argv[]) {
std::vector<int> task_scores;
int n;
std::cin >> n;
for(int i = 0; i < n; i++) {
int sc;
std::cin >> sc;
task_scores.push_back(sc);
}
std::map<std::string, std::vector<size_t>> student_solutions;
std::string command = "";
while(true) {
std::vector<std::string> tok_com;
getline(std::cin, command);
std::stringstream strstream(command);
std::string token = "";
while (getline(strstream, token, ' ')) {
std::cout << token;
tok_com.push_back(token);
}
if (tok_com[0] == "SOLVED") {
std::string name = tok_com[1];
int task = std::stoi(tok_com[2]);
if(std::find(student_solutions[name].begin(), student_solutions[name].end(), task) !=
student_solutions[name].end()) {
student_solutions[name].push_back(task);
}
}
}
return 0;
}
If you comment out if clause, then code works just fine. But if you don't, the code stops with EXC_BAD_ACCESS when trying to cout the token. How can this happen?
But if you don't, the code stops with EXC_BAD_ACCESS when trying to cout the token. How can this happen?
if (tok_com[0] == "SOLVED") {
// ^^^
requires that at least one value was actually stored into the tok_com vector within your loop before.
You should test for tok_com.empty() before dereferencing tok_com:
if (!tok_com.empty() && tok_com[0] == "SOLVED") {
// ^^^^^^^^^^^^^^^^^^^
// ...
}
What you're experiencing actually is undefined behavior varying from exploding fridges, little demons flying out from your nostrils or simply exceptions thrown by your debugging environment or operating system.
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;
}
I keep getting an error Segmentation fault (core dumped), so I ran valgrind. It is my first time using it, so not sure what to do to get my code working. I've tried changing it, but it still says core dumped, or I receive more errors than I had before. I did try debugging the code with gdb, but the debugger was not working properly.
and corresponding product.h
#ifndef GS_PRODUCT
#define GS_PRODUCT
#include <iostream>
#include <string>
using namespace std;
class Product
{
private:
int plu_code;
string name;
double price;
bool by_weight;
double inventory;
public:
Product(int p_code = 0, string p_name = "", bool p_by_weight = true, double p_price = 0.0, double p_inv = 0.0);
bool sold_by_weight(void);
double compute_cost(double weight_or_unit);
string get_name(void);
int get_plu_code(void);
double get_price(void);
double get_inventory(void);
};
#endif
This is my product.cpp:41
#include <iostream>
#include <string>
#include "product.h"
using namespace std;
Product::Product(int p_code, string p_name, bool p_by_weight, double p_price, double p_inv)
{
plu_code = p_code;
name = p_name;
by_weight = p_by_weight;
price = p_price;
inventory = p_inv;
}
bool Product::sold_by_weight(void)
{
return by_weight;
}
double Product::compute_cost(double weight_or_units)
{
inventory -= weight_or_units;
return weight_or_units * price;
}
string Product::get_name(void) {
return name;
}
int Product::get_plu_code(void) {
return plu_code;
}
double Product::get_price(void) {
return price;
}
double Product::get_inventory(void) {
return inventory;
}
This is my main program store
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include "product.h"
#include "Tokenizer.h"
#include "LookupTable.h"
using namespace std;
LookupTable<Product *> table;
int numProducts = 0;
void checkout()
{
}
int main()
{
int plu;
string name;
int weight;
double inv;
double price;
table.addRange(0, 9999);
table.addRange(90000, 99999);
// std::string line;
//Input file
ifstream infile("inventory.csv");
if(infile.fail())
perror("Could not open file ");
stringstream ss;
while(infile.good())
{
string line = "";
//read a product info from file
getline(infile, line);
Tokenizer tok(line, ",");
ss<<line;
//string token = tok.next();
ss >> plu >> name >> weight >> price >>inv;
table[plu] = new Product(plu, name,weight, price,inv);
numProducts++;
}
infile.close();
checkout();
ofstream outfile;
outfile.open("output.csv");
for(int i=0; i< numProducts; i++)
{
outfile<< table[i]-> get_plu_code() << "" << table[i]->get_name()<<""<<table[i]->sold_by_weight() <<""<<table[i]->get_price() <<""<<table[i]->get_inventory();
}
outfile.close();
return 0;
}
The meaning of a segmentation fault is that you tried to access a page which doesn't have the permissions (normally read/write permission but possibly also executable permission) needed for the operation. That is, the system tells you that you tried to access something which isn't really there or which is inaccessible.
There are many typical problems eventually resulting in segmentation faults. Here are a few of those:
An uninitialized pointer is dereferenced.
A null pointer is dereferenced.
An array is accessed outside its boundaries, thus accessing random memory as if it were an array element.
A released object is being used as if it is live, e.g., an object after being deleted or an object which was on the stack.
... and many more similar stuff.
To get help with the actual segmentation fault you have, you'll need to provide a short but complete example exhibiting the problem. Quoting a few lines which you think are related to the problem are generally rather unlikely to actually contain the actual problem.
You don't appear to have any value inventory to return from Product::get_inventory(). I would think that either this wouldn't compile, or you have some code that you haven't shown that is relevant. Most likely, the latter is the case, and the variable inventory is not yet initialized at the time that it is returned.