C++ referencing instances created within a function's scope - c++

Context
The context of the problem is that I am currently writing a small library for use with the Arduino in order to act as a game controller. The problem I am encountering has more to do with C++ than anything Arduino specific however.
I've included the libraries' header and source code below, followed by the Arduino code. I've truncated it where possible.
Problem
In short, only the last switch / action I define actually gets properly handles.
These actions get defined in the Arduino setup function. For example:
controller.addSwitchContinuous(10, 0); // Pin 10; btn index 0
means that pin 10 gets mapped to button 0. When pin 10 is switched closed this is treated as the button being pressed. This works fine for a single action but when I start adding more only the last action actually works. So in the following example only pin 9 is recognized:
controller.addSwitchContinuous(10, 0); // <-- Doesn't work
controller.addSwitchContinuous(9, 1); // <-- Works
This goes for any arbitrary number of actions:
controller.addSwitchContinuous(10, 0); // <-- Doesn't work
controller.addSwitchContinuous(9, 1); // <-- Doesn't work
controller.addSwitchContinuous(8, 2); // <-- Doesn't work
controller.addSwitchContinuous(7, 3); // <-- Works
Potential causes
I am fairly novice with C++ so this I suspect I'm doing something wrong with pointers. More specifically, something seems wrong with how the Joystick_ instance gets passed around.
I have been fiddling with the constructor and trying to use references instead of pointers but I couldn't get it to work properly.
I can confirm the iteration in JFSF::loop does iterate over all actions, if I modify it with:
void JFSF::loop()
{
for (int n = 0; n < _nextActionIndex; n++)
{
if (_actions[n])
{
_actions[n]->loop();
_joystick->setButton(n, PRESSED); // Debug: Set button pressed, regardless of switch.
}
}
if (_doSendState)
{
_joystick->sendState();
}
}
then buttons 0 through n get pressed as expected. It is possible that loop() isn't properly being called, but I would expect it to fail for the N = 1 case as well in that case. Furthermore the fact the last action always succeeds would suggest the iteration is ok.
Full code
// JFSF.h
#ifndef JFSF_h
#define JFSF_h
// ... include for Arduino.h and Joystick.h; bunch of defines
namespace JFSF_PRIV
{
class AbstractAction
{
public:
virtual void loop();
};
/* A Switch that essentially acts as a push button. */
class SwitchContinuousAction : public AbstractAction
{
public:
SwitchContinuousAction(Joystick_ *joystick, int pin, int btnIndex);
void loop();
private:
Joystick_ *_joystick;
int _pin;
int _btnIndex;
};
} // namespace JFSF_PRIV
class JFSF
{
public:
JFSF(Joystick_ *joystick, bool doSendState); // doSendState should be true if Joystick_ does not auto send state.
void loop();
void addSwitchContinuous(int inputPin, int btnIndex);
private:
Joystick_ *_joystick;
JFSF_PRIV::AbstractAction *_actions[MAX_ACTIONS];
int _nextActionIndex;
bool _doSendState;
};
#endif
Source file (trimmed):
// JFSF.cpp
#include "Arduino.h"
#include "Joystick.h"
#include "JFSF.h"
#define PRESSED 1
#define RELEASED 0
// Private classes
namespace JFSF_PRIV
{
SwitchContinuousAction::SwitchContinuousAction(Joystick_ *joystick, int pin, int btnIndex)
{
_joystick = joystick;
_pin = pin;
_btnIndex = btnIndex;
pinMode(_pin, INPUT_PULLUP);
}
void SwitchContinuousAction::loop()
{
int _state = digitalRead(_pin) == LOW ? PRESSED : RELEASED;
_joystick->setButton(_btnIndex, _state);
}
} // namespace JFSF_PRIV
JFSF::JFSF(Joystick_ *joystick, bool doSendState)
{
_joystick = joystick;
_nextActionIndex = 0;
_doSendState = doSendState;
}
void JFSF::addSwitchContinuous(int inputPin, int btnIndex)
{
JFSF_PRIV::SwitchContinuousAction newBtnAction(_joystick, inputPin, btnIndex);
_actions[_nextActionIndex++] = &newBtnAction;
}
void JFSF::loop()
{
for (int n = 0; n < _nextActionIndex; n++)
{
if (_actions[n])
{
_actions[n]->loop();
}
}
if (_doSendState)
{
_joystick->sendState();
}
}
For completeness sake, this is the code for the Arduino, but it is pretty much just declarations:
#include <JFSF.h>
// ... A bunch of const declarations used below. These are pretty self explanatory.
// See: https://github.com/MHeironimus/ArduinoJoystickLibrary#joystick-library-api
Joystick_ joystick(HID_REPORT_ID,
JOYSTICK_TYPE_JOYSTICK, // _JOYSTICK, _GAMEPAD or _MULTI_AXIS
BTN_COUNT, HAT_SWITCH_COUNT,
INCLUDE_X_AXIS, INCLUDE_Y_AXIS, INCLUDE_Z_AXIS,
INCLUDE_RX_AXIS, INCLUDE_RY_AXIS, INCLUDE_RZ_AXIS,
INCLUDE_RUDDER, INCLUDE_THROTTLE,
INCLUDE_ACCELERATOR, INCLUDE_BRAKE, INCLUDE_STEERING);
JFSF controller(&joystick, !DO_AUTO_SEND_STATE);
void setup() {
joystick.begin(DO_AUTO_SEND_STATE);
controller.addSwitchContinuous(10, 0); // <-- Doesn't work
controller.addSwitchContinuous(9, 1); // <-- Works
}
void loop() {
controller.loop();
}
References
ArduinoJoystickLibrary (Source for Joystick_) can be found here: https://github.com/MHeironimus/ArduinoJoystickLibrary#joystick-library-api

I dont really understand your code. Please read How to create a Minimal, Complete and Verifiable example. Anyhow, the following is certainly wrong and likely the cause of your problem:
void JFSF::addSwitchContinuous(int inputPin, int btnIndex)
{
JFSF_PRIV::SwitchContinuousAction newBtnAction(_joystick, inputPin, btnIndex);
_actions[_nextActionIndex++] = &newBtnAction;
}
Lets rewrite it a bit for clarity:
void foo(){
T bar;
container[index] = &bar;
}
What happens here is that bar gets destroyed when it goes out of scope, hence the pointer you put into the container, points to garbage. Presumably somewhere else in your code you are dereferencing those pointers, which is undefined behaviour (aka anything can happen).
Long story short: It is a common pattern among c++ beginners to overuse pointers. Most likely you should make container a container of objects rather than pointers and make use of automatic memory managment instead of trying to fight it.

Thanks to #user463035818 and #drescherjm for identifiying the actual problem.
So in the end I fixed it by simply moving the Action object creation up to the Arduino code (where it's essentially global) and passing references to those objects to the controller.
In code this translates to:
JFSF.cpp
void JFSF::addAction(JFSF_PRIV::AbstractAction *action){
_actions[_nextActionIndex++] = action;
}
Arduino code (ino)
// See code in original post
JFSF controller(&joystick, !DO_AUTO_SEND_STATE);
JFSF_PRIV::SwitchContinuousAction btnOne(&joystick, 10, 0);
JFSF_PRIV::SwitchContinuousAction btnTwo(&joystick, 9, 1);
void setup() {
joystick.begin(DO_AUTO_SEND_STATE);
// controller.addSwitchContinuous(10, 0); // Pin 10; btn index 0
// controller.addSwitchContinuous(9, 1); // Pin 9 ; btn index 1
controller.addAction(&btnOne);
controller.addAction(&btnTwo);
}
// loop() is unchanged

Related

How to Choose Function Based on Loop Iterator

Part of my problem in finding a solution here is likely that I don't know the correct terms for what it is I am asking. For that, I beg forgiveness in advance.
For a microcontroller, I have a list of pins I wish to initiate at the same time. Each has it's own ISR, and calls the same member of a class for each instance but with a pin number as an argument.
I am trying to attach each pin in the array to its corresponding ISR but I would like to choose which ISR by the pin's index. This is Mailer Codeā„¢ and likely does not compile but I believe it's enough to get the idea:
#define PIN1 4
#define PIN2 9
#define PIN3 10
#define PIN4 8
#define PIN5 12
PinAct *pPinact; // Pointer to Counter class
static ICACHE_RAM_ATTR void HandleInterruptsStatic1(void) {
pPinact->handleInterrupts(1);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic2(void) {
pPinact->handleInterrupts(2);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic3(void) {
pPinact->handleInterrupts(3);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic4(void) {
pPinact->handleInterrupts(4);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic5(void) {
pPinact->handleInterrupts(5);
}
class PinAct {
public:
PinAct() {};
void handleInterrupts(int);
}
void PinAct::PinAct() {
int actPins[] = {PIN1, PIN2, PIN3, PIN4, PIN5};
for (int i = 0; i <= sizeof(actPins); i++) {
pinMode(actPin[i], INPUT)
attachInterrupt(digitalPinToInterrupt(KEG1), HandleInterruptsStatic + i, FALLING);
}
}
void PinAct::handleInterrupts(int pin) { // Bubble Interrupt handler
// Do something with pin
}
The goal is to actually make the attachInterrupt(digitalPinToInterrupt(KEG1), HandleInterruptsStatic + i, FALLING); work, choosing which ISR by virtue of the index i.
I need to make other decisions about whether or not to assign the ISR, so concatenating the ISR name to be assigned is desirable.
attachInterrupt(/* ... */, HandleInterruptsStatic + i, /* ... */);
// ^^^^^
In order to select the function you want to call at runtime depending on some integer index i you can use an array of function pointers:
typedef void (*FunctionPointer_t)(void);
FunctionPointer_t functions[] = {
HandleInterruptsStatic1,
HandleInterruptsStatic2,
// ...
};
// to use:
functions[i]();

Using Wire.onRequest by passing a class method?

I have an Arduino sketch that will be working on an Arduino UNO and I am trying to get uno to communicate over the i2c connection with a raspberry pi.
Problem is using wire.h library where method Wire.onRequest is working just fine when I use it like this.
#include <Wire.h>
#define COMM_DELAY 50
#define SLAVE_ADDRESS 0x04
int current_rule = 0;
void initI2c() {
// initialize i2c as slave
Wire.begin(SLAVE_ADDRESS);
// define callbacks for i2c communication
Wire.onReceive(receiveData);
}
// callback for received data
void receiveData(int byteCount) {
while (Wire.available()) {
current_rule = Wire.read();
}
}
but when I try to make this exact result with a class method, I get an error :
invalid use of non-static member function
(with Wire.onRequest(this->receiveData) line gets to be marked red)
Just like this:
void (*funptr)();
typedef void (*Callback)(byte);
class Comm{
public:
int callback_list_size = 0;
bool option_debug;
byte option_address;
int option_comm_delay;
void(*callback_list[256]);
byte *rules;
// function for receiving data. raspberry -> arduino
// Whenever the master sends new data, this method will call the appropriate callback.
void receiveData()
{
byte data;
Serial.println("[INFO] Received new data from master");
while (Wire.available())
{
data = Wire.read();
}
for (int i = 0; i < callback_list_size; i++)
{
if (rules[i] == data){
funptr = callback_list[i];
funptr();
}
}
}
// function for sending data. Called when raspberry request data. arduino -> raspberry
// Whenever the master requests data, this method will be called. For now we don't need this but anyway.
void sendData(int s)
{
if (option_debug)
Serial.println("[INFO] Master requests data!");
}
/* Constructor that takes 3 parameters at max. Only the adress is mandatory others are optional and will be filled with default values
:address - adress of slave(arduino) - Example 0x04
:delay - a delay is needed because I2C clock is quite slow compared to the CPU clock - 50
:debug - for debug purposes if true debug info will be sent to Serial interface - true/false
*/
Comm(byte address, int delay = 50, bool debug = false)
{
option_address = address;
option_comm_delay = delay;
option_debug = debug;
if (debug)
Serial.println("[INFO] Comm Object Created!");
}
// Function needs to be called to initialize the communication channel.
void initI2c()
{
Wire.begin(option_address);
Wire.onReceive(this->sendData);
Wire.onRequest(this->receiveData);
if (option_debug)
Serial.println("[INFO] I2C channel initialized");
}
// Function to add new callback for a rule.
// This function returns id of passed callback
int addCallback(Callback func, byte rule)
{
callback_list_size++;
// Enlarge rules array to keep 1 more byte
byte *temp = new byte[callback_list_size]; // create new bigger array.
for (int i = 0; i + 1 < callback_list_size; i++) // reason fo i+1 is if callback_list_size is 1 than this is the first initializition so we don't need any copying.
{
temp[i] = rules[i]; // copy rules to newer array.
}
delete[] rules; // free old array memory.
rules = temp; // now rules points to new array.
callback_list[callback_list_size - 1] = &func;
rules[callback_list_size - 1] = rule;
return callback_list_size;
}
};
Comm *i2c_comm;
void loop()
{
}
void setup()
{
Serial.begin(9600);
initI2C();
}
void initI2C()
{
i2c_comm = new Comm(0x04, 50, true);
i2c_comm->initI2c();
//Callback Definitions
i2c_comm->addCallback(&rule_1, 0x01);
i2c_comm->addCallback(&rule_2, 0x02);
i2c_comm->addCallback(&rule_3, 0x03);
i2c_comm->addCallback(&rule_4, 0x04);
}
I also tried to make the receiveData method to be static.
But in this case I have an error like this:
invalid use of member Com::callback_list_size in static member function
which makes sense to me as static method won't know which callback_list_size I am talking about.
so I am quite confused about how I can handle such a problem?
You're almost there. Generally speaking in C++ you need to pass a static class method for callback functions.
The error you received after changing your method to static is expected as you're trying to access a member of an instance of the class Comm which cannot be done in a static method in which there is no 'this'.
Here's one of many techniques to consider, but please read over the SO post Using a C++ class member function as a C callback function.
Anyway the approach here is to leverage a static pointer to an instance.
class Comm {
private:
static Comm* pSingletonInstance;
static void OnReceiveHandler() {
if (pSingletonInstance)
pSingletonInstance->receiveData();
}
static void OnSendHandler(int s) {
if (pSingletonInstance)
pSingletonInstance->sendData(s);
}
void initI2c() {
Comm::pSingletonInstance = this; // Assign the static singleton used in the static handlers.
Wire.onReceive(Comm::OnSendHandler);
Wire.onRequest(Comm::OnReceiveHandler);
Wire.begin(option_address);
}
}
// static initializer for the static member.
Comm* Comm::pSingletonInstance = 0;
Again there are many ways to get around this issue but above is an easy one and likely suitable for your project. If you need to manage multiple instances of Comm, you'll have to do something quite different.
Good luck!

C++: both classes do not run concurrently

its my first time here. My code is suppose to make two ultrasonic sensors function at the same time using an mbed. However, i cant seem to make both classes void us_right() and void us_left() in the code run concurrently. Help please :(
#include "mbed.h"
DigitalOut triggerRight(p9);
DigitalIn echoRight(p10);
DigitalOut triggerLeft(p13);
DigitalIn echoLeft(p14);
//DigitalOut myled(LED1); //monitor trigger
//DigitalOut myled2(LED2); //monitor echo
PwmOut steering(p21);
PwmOut velocity(p22);
int distanceRight = 0, distanceLeft = 0;
int correctionRight = 0, correctionLeft = 0;
Timer sonarRight, sonarLeft;
float vo=0;
// Velocity expects -1 (reverse) to +1 (forward)
void Velocity(float v) {
v=v+1;
if (v>=0 && v<=2) {
if (vo>=1 && v<1) { //
velocity.pulsewidth(0.0014); // this is required to
wait(0.1); //
velocity.pulsewidth(0.0015); // move into reverse
wait(0.1); //
} //
velocity.pulsewidth(v/2000+0.001);
vo=v;
}
}
// Steering expects -1 (left) to +1 (right)
void Steering(float s) {
s=s+1;
if (s>=0 && s<=2) {
steering.pulsewidth(s/2000+0.001);
}
}
void us_right() {
sonarRight.reset();
sonarRight.start();
while (echoRight==2) {};
sonarRight.stop();
correctionRight = sonarLeft.read_us();
triggerRight = 1;
sonarRight.reset();
wait_us(10.0);
triggerRight = 0;
while (echoRight==0) {};
// myled2=echoRight;
sonarRight.start();
while (echoRight==1) {};
sonarRight.stop();
distanceRight = ((sonarRight.read_us()-correctionRight)/58.0);
printf("Distance from Right is: %d cm \n\r",distanceRight);
}
void us_left() {
sonarLeft.reset();
sonarLeft.start();
while (echoLeft==2) {};
sonarLeft.stop();
correctionLeft = sonarLeft.read_us();
triggerLeft = 1;
sonarLeft.reset();
wait_us(10.0);
triggerLeft = 0;
while (echoLeft==0) {};
// myled2=echoLeft;
sonarLeft.start();
while (echoLeft==1) {};
sonarLeft.stop();
distanceLeft = (sonarLeft.read_us()-correctionLeft)/58.0;
printf("Distance from Left is: %d cm \n\r",distanceLeft);
}
int main() {
while(true) {
us_right();
us_left();
}
if (distanceLeft < 10 || distanceRight < 10) {
if (distanceLeft < distanceRight) {
for(int i=0; i>-100; i--) { // Go left
Steering(i/100.0);
wait(0.1);
}
}
if (distanceLeft > distanceRight) {
for(int i=0; i>100; i++) { // Go Right
Steering(i/100.0);
wait(0.1);
}
}
}
wait(0.2);
}
You need to use some mechanism to create new threads or processes. Your implementation is sequential, there is nothing you do that tells the code to run concurrently.
You should take a look at some threads libraries (pthreads for example, or if you have access to c++11, there are thread functionality there) or how to create new processes as well as some kind of message passing interface between these processes.
Create two threads, one for each ultrasonic sensor:
void read_left_sensor() {
while (1) {
// do the reading
wait(0.5f);
}
}
int main() {
Thread left_thread;
left_thread.start(&read_left_sensor);
Thread right_thread;
right_thread.start(&read_right_sensor);
while (1) {
// put your control code for the vehicle here
wait(0.1f);
}
}
You can use global variables to write to when reading the sensor, and read them in your main loop. The memory is shared.
Your first problem is that you have placed code outside of your infinite while(true) loop. This later code will never run. But maybe you know this.
int main() {
while(true) {
us_right();
us_left();
} // <- Loops back to the start of while()
// You Never pass this point!!!
if (distanceLeft < 10 || distanceRight < 10) {
// Do stuff etc.
}
wait(0.2);
}
But, I think you are expecting us_right() and us_left() to happen at exactly the same time. You cannot do that in a sequential environment.
Jan Jongboom is correct in suggesting you could use Threads. This allows the 'OS' to designate time for each piece of code to run. But it is still not truly parallel. Each function (classes are a different thing) will get a chance to run. One will run, and when it is finished (or during a wait) another function will get its chance to run.
As you are using an mbed, I'd suggest that your project is an MBED OS 5 project
(you select this when you start a new project). Otherwise you'll need to use an RTOS library. There is a blinky example using threads that should sum it up well. Here is more info.
Threading can be dangerous for someone without experience. So stick to a simple implementation to start with. Make sure you understand what/why/how you are doing it.
Aside: From a hardware perspective, running ultrasonic sensors in parallel is actually not ideal. They both broadcast the same frequency, and can hear each other. Triggering them at the same time, they interfere with each other.
Imagine two people shouting words in a closed room. If they take turns, it will be obvious what they are saying. If they both shout at the same time, it will be very hard!
So actually, not being able to run in parallel is probably a good thing.

Issue with setting speed to DifferentialWheels in Webots C++

Small community here, but hopefully somebody sees this. I'm attempting to do a pure C++ implementation of a Webots simulation for an E-puck. The C++ documentation is sorely lacking, and I can't seem to find a resolution for this issue (the C implementation is stellar, but all the function calls were changed for C++).
Essentially, I'm just trying to get a simple application up and running...I want to make the E-puck move forward. I will post the entirety of my code below...all I'm doing is instantiating a Robot entity, printing out all the IR sensor values, and attempting to move it forward.
The issue is that it does not move. I'd think that there would be some call to link the DifferentialWheel object to the E-puck (similar to the camera = getCamera("camera") call).
If I comment out my call to setSpeed, the program works perfectly (doesn't move, but prints values). If I leave it in, the simulation freezes up after a single step, once it gets to that call. I'm not exactly sure what I'm doing wrong, to be honest.
// webots
#include <webots/Robot.hpp>
#include <webots/Camera.hpp>
#include <webots/DistanceSensor.hpp>
#include <webots/DifferentialWheels.hpp>
#include <webots/LED.hpp>
// standard
#include <iostream>
using namespace webots;
#define TIME_STEP 16
class MyRobot : public Robot
{
private:
Camera *camera;
DistanceSensor *distanceSensors[8];
LED *leds[8];
DifferentialWheels *diffWheels;
public:
MyRobot() : Robot()
{
// camera
camera = getCamera("camera");
// sensors
distanceSensors[0] = getDistanceSensor("ps0");
distanceSensors[1] = getDistanceSensor("ps1");
distanceSensors[2] = getDistanceSensor("ps2");
distanceSensors[3] = getDistanceSensor("ps3");
distanceSensors[4] = getDistanceSensor("ps4");
distanceSensors[5] = getDistanceSensor("ps5");
distanceSensors[6] = getDistanceSensor("ps6");
distanceSensors[7] = getDistanceSensor("ps7");
for (unsigned int i = 0; i < 8; ++i)
distanceSensors[i]->enable(TIME_STEP);
// leds
leds[0] = getLED("led0");
leds[1] = getLED("led1");
leds[2] = getLED("led2");
leds[3] = getLED("led3");
leds[4] = getLED("led4");
leds[5] = getLED("led5");
leds[6] = getLED("led6");
leds[7] = getLED("led7");
}
virtual ~MyRobot()
{
// cleanup
}
void run()
{
double speed[2] = {20.0, 0.0};
// main loop
while (step(TIME_STEP) != -1)
{
// read sensor values
for (unsigned int i = 0; i < 8; ++i)
std::cout << " [" << distanceSensors[i]->getValue() << "]";
std::cout << std::endl;
// process data
// send actuator commands
// this call kills the simulation
// diffWheels->setSpeed(1000, 1000);
}
}
};
int main(int argc, char* argv[])
{
MyRobot *robot = new MyRobot();
robot->run();
delete robot;
return 0;
}
Now, if this were the C implementation, I would call wb_differential_wheels_set_speed(1000, 1000); However, that call isn't available in the C++ header files.
The problem causing the freeze is due to the use of the uninitialized variable diffWheels.
DifferentialWheels (as well as Robot and Supervisor) doesn't need to be initialized.
You have to change the base class of your MyRobot class to DifferentialWheels
class MyRobot : public DifferentialWheels
and then simply call
setSpeed(1000, 1000)
and not
diffWheels->setSpeed(1000, 1000)
It doesn't seem as though you've initialized diffWheels, so I would imagine you're getting a segfault from dereferencing a garbage pointer. Try putting
diffWheels = new DifferentialWheels;
in the constructor of MyRobot.

Threads C++, Access Violation reading location x error

Platform : Windows 7
I'm developing a project for known text cipher attack in which;
Main process creates n child processes
Child processes decrypt an encrypted string, key subspace is partitioned according to number of child processes
Communication between child processes are by a static variable
for(int i = 0; i<info.totalNumberOfChildren; i++)
{
startChild( &info.childInfoList[i]);
//_beginthread(startChild, 0, &info.childInfoList[i]);
}
Above code works fine since:
First child starts execution, the key is set as a number such as 8 for testing purposes which is within the first child's partition, so first child finds the key, reports and sets true the killSwitch.
All the other children that are created are closed even before checking the first key as the killSwitch is true.
When I however do this :
for(int i = 0; i<info.totalNumberOfChildren; i++)
{
//startChild( &info.childInfoList[i]);
_beginthread(startChild, 0, &info.childInfoList[i]);
}
I get an access violation error. What could possibly be my source of error ?
Edit: I will try to share as relevant code as I can
startChild does the following:
void startChild( void* pParams)
{
ChildInfo *ci = (ChildInfo*)pParams;
// cout<<"buraya geldi"<<endl;
ChildProcess cp(*ci);
// write to log
cp.completeNextJob();
}
childInfo holds the following :
// header file
class ChildInfo
{
public:
ChildInfo();
ChildInfo(char * encrypted, char * original, static bool killSwitch, int totalNumOfChildren, int idNum, int orjLen);
void getNextJob();
bool keyIsFound();
Des des;
void printTest();
bool stopExecution;
bool allIsChecked;
char * encyptedString;
char * originalString;
int id;
int orjStrLen;
private:
int lastJobCompleted;
int totalNumberOfChildren;
int jobDistBits;
};
completeNextJob() does the following :
void ChildProcess::completeNextJob()
{
cout<<"Child Id : "<<info.id<<endl;
// cout<<"Trying : "<<info.encyptedString<<endl; // here I got an error
char * newtrial = info.encyptedString;
char * cand = info.des.Decrypt(newtrial); // here I also get an error if I comment out
/*
cout<<"Resultant : "<<cand<<endl;
cout<<"Comparing with : "<<info.originalString<<endl;
*/
bool match = true;
for(int i = 0; i<info.orjStrLen; i++)
{
if(!(cand[i] == info.originalString[i]))
match = false;
}
if(match)
{
cout<<"It has been acknowledged "<<endl;
info.stopExecution = true;
return;
}
else
{
if(!info.keyIsFound())
{
if(!info.allIsChecked)
{
info.getNextJob();
completeNextJob();
}
else
{
}
}
else
{
}
}
}
decrypt() method does the following :
char * Des::Decrypt(char *Text1)
{
int i,a1,j,nB,m,iB,k,K,B[8],n,t,d,round;
char *Text=new char[1000];
unsigned char ch;
strcpy(Text,Text1); // this is where I get the error
i=strlen(Text);
keygen();
int mc=0;
for(iB=0,nB=0,m=0;m<(strlen(Text)/8);m++) //Repeat for TextLenth/8 times.
{
for(iB=0,i=0;i<8;i++,nB++)
{
ch=Text[nB];
n=(int)ch;//(int)Text[nB];
for(K=7;n>=1;K--)
{
B[K]=n%2; //Converting 8-Bytes to 64-bit Binary Format
n/=2;
} for(;K>=0;K--) B[K]=0;
for(K=0;K<8;K++,iB++) total[iB]=B[K]; //Now `total' contains the 64-Bit binary format of 8-Bytes
}
IP(); //Performing initial permutation on `total[64]'
for(i=0;i<64;i++) total[i]=ip[i]; //Store values of ip[64] into total[64]
for(i=0;i<32;i++) left[i]=total[i]; // +--> left[32]
// total[64]--|
for(;i<64;i++) right[i-32]=total[i];// +--> right[32]
for(round=1;round<=16;round++)
{
Expansion(); //Performing expansion on `right[32]' to get `expansion[48]'
xor_oneD(round);
substitution();//Perform substitution on xor1[48] to get sub[32]
permutation(); //Performing Permutation on sub[32] to get p[32]
xor_two(); //Performing XOR operation on left[32],p[32] to get xor2[32]
for(i=0;i<32;i++) left[i]=right[i]; //Dumping right[32] into left[32]
for(i=0;i<32;i++) right[i]=xor2[i]; //Dumping xor2[32] into right[32]
} //rounds end here
for(i=0;i<32;i++) temp[i]=right[i]; // Dumping -->[ swap32bit ]
for(;i<64;i++) temp[i]=left[i-32]; // left[32],right[32] into temp[64]
inverse(); //Inversing the bits of temp[64] to get inv[8][8]
/* Obtaining the Cypher-Text into final[1000]*/
k=128; d=0;
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
d=d+inv[i][j]*k;
k=k/2;
}
final[mc++]=(char)d;
k=128; d=0;
}
} //for loop ends here
final[mc]='\0';
char *final1=new char[1000];
for(i=0,j=strlen(Text);i<strlen(Text);i++,j++)
final1[i]=final[j]; final1[i]='\0';
return(final);
}
Windows is trying to tell you why your program crashed. Please use a debugger to see what Windows is talking about. Location X is important: it should tell you whether your program is dereferencing NULL, overflowing a buffer, or doing something else. The call stack at the time of the crash is also very important.
Debugger is your best friend, try to use it and check step by step what could cause this access violation.
I think that info.encyptedString is not initialized correctly and pointing to not allocated memory, but I cant be sure because you didn't show this part of code.
And of course you must protect your shared resources (info) using some synchronization objects like critical section or mutex or semaphore.
I don't know, the basic issue seems pretty straightforward to me. You have multiple threads executing simultaneously, which access the same information via *pParams, which presumably is of type ChildInfo since that's what you cast it to. That info must be getting accessed elsewhere in the program, perhaps in the main thread. This is corrupting something, which may or may not have to do with Text1 or info.id, these errors can often be 'non-local' and hard to debug for this reason. So start mutex-protecting the entire thread (within your initial loop), and then zero in on the critical sections by trial and error, i.e. mutex-protect as small a region of code as you can get away with without producing errors.