Why do I get a segmentation fault when using pthread_join? - c++

Here is the code I have, it compiles and runs using g++ but I get a segmentation fault. I know it happens around the pthread_join statement but I cant figure out why.
#include <iostream>
#include <stdio.h>
#include <fstream>
#include <pthread.h>
#include <stdlib.h>
#include <sstream>
using namespace std;
struct data{
string filename;
int x;
int y;
};
void *threadFunction(void *input){
data *file = (data *) input;
string filename = file->filename;
ifstream myFile;
int xCount = 0;
int yCount = 0;
myFile.open(filename.c_str());
string line;
while(myFile >> line){
if(line == "X"){
xCount++;
}else if(line == "Y"){
yCount++;
}
}
file->x = xCount;
file->y = yCount;
return (void *) file;
}
int main(){
pthread_t myThreads[20];
data *myData = new data[20];
for(int i = 0; i < 20; i++){
ostringstream names;
names << "/filepath/input" << i+1 << ".txt";
myData[i].filename = names.str();
myData[i].x = 0;
myData[i].y = 0;
}
for(int i = 0; i < 20; i++){
int check = pthread_create(&myThreads[i], NULL, threadFunction, (void *) &myData[i]);
if(check != 0){
cout << "Error Creating Thread\n";
exit(-1);
}
}
int xCount = 0;
int yCount = 0;
for(int i = 0; i < 20; i++){
data* returnedItem;
pthread_join(myThreads[i], (void**) returnedItem);
xCount += returnedItem->x;
yCount += returnedItem->y;
}
cout << "Total X: " << xCount << "\n";
cout << "Total Y: " << yCount << "\n";
}
Am I not calling return properly from my threadFunction? I've been trying a bunch of different things and I still don't know what's going on...any help would be greatly appreciated! (the text file I open contain either an X or Y per line. My goal is to count the total number of Xs and Ys in 20 text files)

Second argument of pthread_join will be used to return, return value of the thread, so somewhere inside pthread_join we have a code that call *secondArgument = thread_return_value, but lets look at what you are doing here:
// You are not initializing returnedItem, so it contain some garbage value
// For example 0x12345678
data* returnedItem;
// Now you cast that garbage to (void**), and pthread_join will call
// *(0x12345678) = thread_return_value that will cause segmentation fault
pthread_join(myThreads[i], (void**) returnedItem);
But you want return value to be copied to returnedItem, am I right? in case that you answer is yes you should pass address of returnedItem to pthread_join so it can copy it there. So change your call to:
pthread_join(myThreads[i], (void**) &returnedItem);

pthread_join(myThreads[i], (void**) returnedItem);
should be
pthread_join(myThreads[i], (void**) &returnedItem);
You're asking join to set the value of returnedItem to be whatever void* your thread function returned ... so you need to give the address of returnedItem.

The second argument to pthread_join() is a void** into which the result is to be stored. You are passing a random value, however. This could should rather look something like this:
void* result;
pthread_join(myThread[i], &result);
data* returnedItem = static_cast<data*>(result);
Of course, this assumes that a data* was, indeed, returned.

Related

2 Dimension Arrays memory segment fault in C++

I made dynamic allocation and array initialization functions with cpp, but I got a segmentation error The code I wrote is below.
#include <iostream>
#define User_Height 100
#define User_Width 100
using namespace std;
void Creat_Array(int** _pp_Created_Array)
{
_pp_Created_Array = new int*[User_Width];
for (int x = 0; x < User_Height ; x++)
{
_pp_Created_Array[x] = new int[User_Height];
}
if(_pp_Created_Array == NULL)
{
cout<<"""fail to alloc memory.""" <<endl;
return;
}
else
{
cout << "[_pp_Created_Array] memory first address : ";
cout << _pp_Created_Array << endl << endl;
}
}
void Initialize_Array(int** _pp_Initialized_Array)
{
for (int x = 0; x < User_Width; x++)
{
for (int y = 0; y < User_Height; y++)
{
_pp_Initialized_Array[x][y] = 0; //*segment fault*
}
}
}
And I checked the function function created
int main()
{
//debug
int** debugArray = nullptr;
cout << "start creat array" <<endl;
Creat_Array(debugArray);
cout << "start initial array" <<endl;
Initialize_Array(debugArray);
return 0;
}
and compile console is (VScode , g++)
start creat array
[_pp_Created_Array] memory first address : 0x8a6f40
start initial array
The terminal process "C:\Windows\System32\cmd.exe /d /c cmd /C
C:\Users\pangpany\project\PathfinderTest\main" failed to launch (exit code:
3221225477).
But I got a segment fault error in void Initialize_Array(int** _pp_Initialized_Array) function
I can't figure out is there anyone who can help?
So the problem is that you never return the array from the Creat_Array function. and so when you come to use the array you are using an uninitialised variable.
Write Creat_Array with a return value instead of a parameter, like this
int** Creat_Array()
{
int** _pp_Created_Array = ...;
...
return _pp_Created_Array;
}
int main()
{
cout << "start creat array" <<endl;
int** debugArray = Creat_Array();
...
}
Changing a variable inside a function does not change any variable outside the function. debugArray and _pp_Created_Array are two different variables.
Also this code is wrong
if(_pp_Created_Array == NULL)
new never returns NULL so this test will always be false. If new fails it throws an exception, it doesn't return NULL.

Convert String in to MAC address [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 5 years ago.
Inside the file in SPIFFS, I'm saving information about the mac address in the form "XX:XX:XX:XX:XX:XX".
When I read the file, I need to switch it from STRING to a array of hexadecimal values.
uint8_t* str2mac(char* mac){
uint8_t bytes[6];
int values[6];
int i;
if( 6 == sscanf( mac, "%x:%x:%x:%x:%x:%x%*c",&values[0], &values[1], &values[2],&values[3], &values[4], &values[5] ) ){
/* convert to uint8_t */
for( i = 0; i < 6; ++i )bytes[i] = (uint8_t) values[i];
}else{
/* invalid mac */
}
return bytes;
}
wifi_set_macaddr(STATION_IF, str2mac((char*)readFileSPIFFS("/mac.txt").c_str()));
But I'm wrong in the code somewhere
When i put AA:00:00:00:00:01 in file, my ESP8266 set 29:D5:23:40:00:00
I need help, thank you
You are returning a pointer to a "local" variable, i.e. one which's lifetime ends when the function is finished. Using such a pointer then is UB, which may be, for example, the behaviour you are seeing.
To overcome this, you could pass the array as parameter; then the caller is responsible for memory management.
BTW: you could use format %hhx to read in directly into an 8 bit unsigned data type:
int str2mac(const char* mac, uint8_t* values){
if( 6 == sscanf( mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",&values[0], &values[1], &values[2],&values[3], &values[4], &values[5] ) ){
return 1;
}else{
return 0;
}
}
int main() {
uint8_t values[6] = { 0 };
int success = str2mac("AA:00:00:00:00:01", values);
if (success) {
for (int i=0; i<6; i++) {
printf("%02X:",values[i]);
}
}
}
Your code doesn't seem to be compatible with wifi_set_macaddr (I looked up API documentation). It expects a uint8 pointer to mac address, which means the way you wrote it is not going to work (returning pointer to local variable etc). Here is an example which you should be able to adapt to your purpouse:
#include <iostream>
#include <fstream>
// mock up/print result
bool wifi_set_macaddr(uint8_t index, uint8_t *mac)
{
std::cout << "index: " << (int)index << " mac: ";
for (int i = 0; i < 6; ++i)
std::cout << std::hex << (int)mac[i] << " ";
std::cout << std::endl;
return true;
}
// test file
void writeTestFile()
{
std::ofstream ofs("mac.txt");
if (!(ofs << "AA:00:00:00:00:01" << std::endl))
{
std::cout << "File error" << std::endl;
}
ofs.close();
}
int main()
{
writeTestFile();
uint8_t mac[6];
int i = 0, x;
std::ifstream ifs("mac.txt");
for (; i < 6 && ifs >> std::hex >> x; ++i)
{
mac[i] = static_cast<uint8_t>(x);
ifs.ignore();
}
if (i < 6)
{
std::cout << "File error or invalid MAC address" << std::endl;
return 1;
}
wifi_set_macaddr(0x00, mac);
return 0;
}
http://coliru.stacked-crooked.com/view?id=d387c628e590a467

Assigning a struct pointer value from struct vector

#include <iostream>
#include <vector>
using namespace std;
struct Sn {
int SnId;
double spentEnergy;
};
class Node {
//other stuff
private:
vector<Sn> SnRecord;
public:
int getBestSn(Sn* bestSn);
void someFunction();
};
int main()
{
Node nd;
nd.someFunction();
return 0;
}
void Node::someFunction() {
//adding some records in vector just for testing purpose
Sn temp;
temp.SnId = 1; temp.spentEnergy = 5;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
cout << "Size of SnReocord is " << SnRecord.size() << endl;
//choosing best sn
Sn *bestSn;
int returnCode = -1;
returnCode = getBestSn(bestSn);
if (returnCode == 0){ //means there is a best SN
cout<< "Found best SN with id = "<< bestSn->SnId << endl;
}
else {
cout <<"NO SN "<< endl;
}
}
int Node::getBestSn(Sn* bestSn) {
int tblSize = (int)SnRecord.size();
if (tblSize == 0)
return -1;
//here i have to assign *bestSn a selected value from vector
//suppose SnRecord[2] is best Sn
cout << "Best sn id is " << SnRecord[2].SnId<< endl; //works OK,
bestSn = &SnRecord[2]; ///// giving me core dump ERROR in my own program but in this simplified version it only gives wrong value
return 0;
}
The output now is:
Size of SnReocord is 3
Best sn id is 2
Found best SN with id = 520004336
In my own program it gives me Core dump error, if I comment this line (and make proper other comments according to function call), the error is gone and simulation executes normally.
I saw examples with arrays, the work if a pointer is assigned a value in this way:
int numbers[5];
int * p;
p = &numbers[2]; //works OK.
but for vectors its not working. Or may be its problem of vector of structures, I'm unable to figure out. Any suggestions?
Ok actually the problem is solved by using suggestion of Sn* & bestSn. But I don't understand this solution. Why can't I pass a pointer variable and it saves a pointer value in it which latter could be accessed?

After passing pointer to the main function, cannot print the content properly

I am practicing using pointers to create objects and access data. I created a stuct called BigNum to represent a number with multiple digits. When I try to print the content of the struct inside the readDigits function, it can be printed pretty well. However, after passing the pointer to the main function, the content of the stuct is printed out to be random numbers. Why? How to fix it?
struct BigNum{
int numDigits; //the number of digits
int *digits; //the content of the big num
};
int main(){
BigNum *numPtr = readDigits();
for (int i=0; i<(numPtr->numDigits);i++ ){
std::cout << (numPtr->digits)[i] << std::endl;
}
return 0;
}
BigNum* readDigits(){
std::string digits;
std::cout << "Input a big number:" << std::endl;
std::cin >> digits;
int result[digits.length()];
toInt(digits,result);
BigNum *numPtr = new BigNum();
numPtr->numDigits = digits.length();
numPtr->digits = result;
/* When I try to print in here, it's totally okay!
std::cout << "Here is the content:" << std::endl;
for (int i=0; i<numPtr->numDigits;i++ ){
std::cout << (numPtr->digits)[i] << std::endl;
}
*/
return numPtr;
}
void toInt(std::string& str, int result[]){
for (int i=0;i<str.length() ;i++ ){
result[str.length()-i-1] = (int)(str[i]-'0');
}
}
BigNum* readDigits(){
//....
int result[digits.length()];
//....
numPtr->digits = result;
return numPtr;
}
result is stored on the stack. So if you return it as part of numPtr, it will be invalid as soon as you exit the function. Instead of storing it on the stack you have to allocate it with new.
You have undefined behavior because you assign address of automatic object to digits pointer. When readDigits() returns this memory is not valid anymore. You should assign to this pointer address of heap-based object (or some equivalent, e.g. use vector or smart pointer):
#include <vector>
struct BigNum{
int numDigits; //the number of digits
std::vector<int> digits; //the content of the big num
};
Then you can insert numbers into vector this way:
int input;
while ( std::cin >> input) //enter any non-integer to end the loop
{
digits.push_back(input);
}
The problem is that within the function BigNum* readDigits() you assign apointer to stack memory to the pointer of your newly allocated BigNum:
int result[digits.length()]; // <--- variable is on the stack!!!
toInt(digits,result);
BigNum *numPtr = new BigNum();
numPtr->numDigits = digits.length();
numPtr->digits = result; // <--- make pointer to stack memory available to caller of readDigits
Now if you proceed the access to numPtr->digits is ok since the memory of result is still valid on the stack (as long as you are within readDigits). Once you've left ´readDigits()´ the memory of result is overwritten depending on what you do (calling other functions, ...).
Right now I'm even wondering why you don't get a compiler error with ´int result[digits.length()];´ since ´digits.length()´ is not constant and the size of required stack memory has to be defined at compile time... so I'm thinking that the size of result is actually 0...?? Would be a nice thing to test!
My recommendation is to modify the code of readDigits as follows:
BigNum* readDigits()
{
std::string digits;
int i;
std::cout << "Input a big number:" << std::endl;
std::cin >> digits;
//int result[digits.length()];
//toInt(digits,result);
BigNum *numPtr = new BigNum();
numPtr->numDigits = digits.length();
numPtr->digits = (int *)malloc(sizeof(int) * numPtr->numDigits); // allocate heap memory for digits
toInt(digits, numPtr->digits);
/* When I try to print in here, it's totally okay!
std::cout << "Here is the content:" << std::endl;
for (i = 0; i <numPtr->numDigits; i++)
{
std::cout << (numPtr->digits)[i] << std::endl;
}
*/
return numPtr;
}
Remember to free your memory if ´BigNum *numPtr´ is no longer used (´free(numPtr->digits);´) otherwise you'll get a memory leak (sooner or later):
int main()
{
BigNum *numPtr = readDigits();
int i;
for (i = 0; i < (numPtr->numDigits); i++)
{
std::cout << (numPtr->digits)[i] << std::endl;
}
free(numPtr->digits); // free memory allocated by readDigits(..)
return 0;
}

C++ Returning results from several threads into an array

I've a pattern-matching program which takes as input a string and returns a string closely matched by a dictionary. Since the algorithm takes several seconds to run one match query, I am attempting to use multi-threading to run batch queries.
I first read in a file containing a list of queries and for each query dispatch a new thread to perform the matching algorithm, returning the results into an array using pthread_join.
However, I'm getting some inconsistent results. For example, if my query file contains the terms "red, green, blue", I may receive "red, green, green" as the result. Another run may generate the correct "red, green, blue" result. It appears to sometimes be writing over the result in the array, but why would this happen since the array value is set according to the thread id?
Dictionary dict; // global, which performs the matching algorithm
void *match_worker(void *arg) {
char* temp = (char *)arg;
string strTemp(temp);
string result = dict.match(strTemp);
return (void *)(result.c_str());
}
void run(const string& queryFilename) {
// read in query file
vector<string> queries;
ifstream inquery(queryFilename.c_str());
string line;
while (getline(inquery, line)) {
queries.push_back(line);
}
inquery.close();
pthread_t threads[queries.size()];
void *results[queries.size()];
int rc;
size_t i;
for (i = 0; i < queries.size(); i++) {
rc = pthread_create(&threads[i], NULL, match_worker, (void *)(queries[i].c_str()));
if (rc) {
cout << "Failed pthread_create" << endl;
exit(1);
}
}
for (i = 0; i < queries.size(); i++) {
rc = pthread_join(threads[i], &results[i]);
if (rc) {
cout << "Failed pthread_join" << endl;
exit(1);
}
}
for (i = 0; i < queries.size(); i++) {
cout << (char *)results[i] << endl;
}
}
int main(int argc, char* argv[]) {
string queryFilename = arg[1];
dict.init();
run(queryFilename);
return 0;
}
Edit: As suggested by Zac, I modified the thread to explicitly put the result on the heap:
void *match_worker(void *arg) {
char* temp = (char *)arg;
string strTemp(temp);
int numResults = 1;
cout << "perform match for " << strTemp << endl;
string result = dict.match(strTemp, numResults);
string* tmpResult = new string(result);
return (void *)((*tmpResult).c_str());
}
Although, in this case, where would I put the delete calls? If I try putting the following at the end of the run() function it gives an invalid pointer error.
for (i = 0; i < queries.size(); i++) {
delete (char*)results[i];
}
Without debugging it, my guess is that it has something to do with the following:
void *match_worker(void *arg)
{
char* temp = (char *)arg;
string strTemp(temp);
string result = dict.match(strTemp); // create an automatic
return (void *)(result.c_str()); // return the automatic ... but it gets destructed right after this!
}
So when the next thread runs, it writes over the same memory location you are pointing to (by chance), and you are inserting the same value twice (not writing over it).
You should put the result on the heap to ensure it does not get destroyed between the time your thread exits and you store it in your main thread.
With your edit, you are trying to mix things up a bit too much. I've fixed it below:
void *match_worker(void *arg)
{
char* temp = (char *)arg;
string strTemp(temp);
int numResults = 1;
cout << "perform match for " << strTemp << endl;
string result = dict.match(strTemp, numResults);
string* tmpResult = new string(result);
return (void *)(tmpResult); // just return the pointer to the std::string object
}
Declare results as
// this shouldn't compile
//void* results[queries.size()];
std::string** results = new std::string[queries.size()];
for (int i = 0; i < queries.size(); ++i)
{
results[i] = NULL; // initialize pointers in the array
}
When you clean up the memory:
for (i = 0; i < queries.size(); i++)
{
delete results[i];
}
delete [] results; // delete the results array
That said, you would have a much easier time if you used the C++11 threading templates instead of mixing the C pthread library and C++.
The problem is caused by the lifetime of the local variable result and the data returned by the member function result.c_str(). You make this task unnecessary difficult by mixing C with C++. Consider using C++11 and its threading library. It makes the task much easier:
std::string match_worker(const std::string& query);
void run(const std::vector<std::string>& queries)
{
std::vector<std::future<std::string>> results;
results.reserve(queries.size());
for (auto& query : queries)
results.emplace_back(
std::async(std::launch::async, match_worker, query));
for (auto& result : results)
std::cout << result.get() << '\n';
}