std::map pass by reference Pointer to Object - c++

I'm coding a plugin for XPLANE10 which gets a MSG from ROS.
My IDE is QTcreator 4.1.0 based QT 5.7.0 for Ubuntu 64 Bit. I would like to use C++11 Standards
My code explained
The main initializes ROS and creates a map -> container.
ROS spins in a loop till my GUI sends a MSG where my AirPlane should fly.
The MSG contains 3 floats(phi, theta, psi) where "phi" is the AirPlane ID, theta contains the ID for my ETA(Estimated Time of Arrival)
and psi contains the ID for my pose All of the IDs are saved in the ParameterServer(lookuptable).
So at the beginning i look up the activeAirplanes which returns a vector . I would like to store them in a map where the key is the AirCraft ID and the second param is an instance of the Object.
So i have initialized the for example(looked in container while debugging):
[0] first = 1 // Airplane ID1
[0] second = new CObject(freq)
[1] first = 2 // Airplane ID2
[1] second = new CObject(freq)
If i get a MSG from GUI
phi = 1
theta=2
psi=3
,
ROS will callback
MSG(....std::map<i32, CObject> &container)
// if phi is 1 so use the mapkey 1 and trigger the method do_stuff from CObject
do_stuff(phi, theta, psi,freq)
I would like to call the in a function from main
int getPlanes(std::map<i32,CObject>& container)
{
...
getActiveAirplanesFromServer(activePlanes);
}
First Question:
How do i pass the container to my callback?
Second Question:
How do i parallelize do_stuff() so my callback will return to main and i'm able to command more aircrafts while the others are calculated?
Third Question:
How would be the correct syntax for getPlanes to pass the container by reference so getPlanes() can edit it?
Fourth Question:
Is there a difference between
std::map<i32,CObject*> map
std::map<i32,CObject>* map
and
std::map<i32,CObject*>::iterator it=container->begin();
std::map<i32,CObject*>::iterator* it=container->begin();
If yes, what do i want ? #4Solved
// I have to edit stuff 'cause of some restrictions in my company.
#include "Header.h"
int main()
{
f64 freq = 10;
std::map<i32, CObject>* container;
std::map<i32,CObject>::iterator* it=container->begin();
// ROS
if(!ros::isInitialized())
{
int rosargc = 0;
char** rosargv = NULL;
ros::init(rosargc, rosargv, "MainNode");//), ros::init_options::AnonymousName);
}
else
{
printf("Ros has already been initialized.....\n");
}
ros::NodeHandle* mainNodeHandle=new ros::NodeHandle;
ros::AsyncSpinner spinner(2);
ParameterServer * ptrParam= new ParameterServer(mainNodeHandle);
ros::Subscriber airSub=mainNodeHandle->subscribe<own_msgs::ownStruct>("/MSG",
1000,
boost::bind(MSG,
_1,
freq,
container));
std::vector<i32> activePlanes;
i32 retVal=0;
retVal += ptrParam-> ParameterServer::getActiveAirplanesFromServer(activePlanes);
if (retVal == 0 && activePlanes.size()>0)
{
for (u32 j =0; j <activePlanes.size(); j++)
{
container->insert (std::pair<i32,CObject> (activePlanes[j] , new CObject(freq)));
}
}
while (ros::ok())
{
spinner.start(); //spinnt sehr viel :-)
ros::waitForShutdown ();
}
std::cout<<"ENDE"<<std::endl;
int retval = 1;
return retval;
}
void MSG(const own_msgs::ownStruct<std::allocator<void> >::ConstPtr &guiMSG,
f64 freq,
std::map<i32, CObject> &container)
{
if ((guiMSG->phi != 0) && (guiMSG->theta != 0) && (guiMSG->psi != 0))
{
std::string alpha = std::to_string(guiMSG->phi)+std::to_string(guiMSG->theta)+to_string(guiMSG->psi);
container.at(guiMSG->phi) -> do_stuff(guiMSG->phi,guiMSG->theta,guiMSG->psi, freq);
}
else
{
std::cout<<" Did not receive anything\n"<<endl;
}
}
void do_stuff(...)
{
//copy the IDs to private Member of this single Object
//setROS() for this single Object
//callback the current AC pose via ID from XPLANE
//callback the wished AC pose via ID from ParamServer
// do some calculations for optimum flight path
// publish the Route to XPlane
}
EDIT::
Problem is i get it to compile now and if debug it and set a breakpoint at :
void MSG(const own_msgs::ownStruct<std::allocator<void> >::ConstPtr &guiMSG,f64 freq,std::map<i32, CObject*> &container)
{
..
/*->*/ container.at(guiMSG->)...
}
The Container remains empty.

So i read some stuff about pointers and i saw my errors..
I confused * and &
if i want to pass the adress of a variable i have to write like
int main()
{
int a = 0;
AddTwo(&a)
cout<<a<<endl; // Output: 2
}
void AddTwo(int* a)
{
a+=2;
}

Related

physx multithreading copy transform data

I have a scene with tons of similar objects moved by physx, and i want to draw all of this using opengl instansing. So, i need to form a array with transform data of each object and pass it in to opengl shader. And, currently, filling an array is bottleneck of my app, because physx simulation using 16 thread, but creating array use just one thread.
So, i created data_transfer_task class, which contain two indexes, start and stop and move transform data of physx objects between this indexes to array.
class data_transfer_task : public physx::PxTask {
public:
int start;
int stop;
start_transfer_task* base_task;
data_transfer_task(int start, int stop, start_transfer_task* task, physx::PxTaskManager *mtm) :physx::PxTask() {
this->start = start;
this->stop = stop;
this->mTm = mtm;
base_task = task;
}
void update_transforms();
virtual const char* getName() const { return "data_transfer_task"; }
virtual void run();
};
void data_transfer_task::update_transforms() {
for (int i = start; i < stop; i++) {
auto obj = base_task->objects->at(i);
auto transform = obj->getGlobalPose();
DrawableObject* dr = (DrawableObject*)obj->userData;
auto pos = transform.p;
auto rot = transform.q;
dr->set_position(glm::vec3(pos.x, pos.y, pos.z));
dr->set_rotation(glm::quat(rot.w, rot.x, rot.y, rot.z));
}
}
void data_transfer_task::run() { update_transforms(); }
I created another class start_transfer_task, which creates and sheduled tasks according to thread count.
class start_transfer_task : public physx::PxLightCpuTask{
public:
start_transfer_task(physx::PxCpuDispatcher* disp, std::vector<physx::PxRigidDynamic*>* obj, physx::PxTaskManager* mtm) :physx::PxLightCpuTask() {
this->mTm = mtm;
this->dispatcher = disp;
this->objects = obj;
}
physx::PxCpuDispatcher* dispatcher;
std::vector<physx::PxRigidDynamic*>* objects;
void start();
virtual const char* getName() const { return "start_transfer_task"; }
virtual void run();
};
void start_transfer_task::start() {
int thread_count = dispatcher->getWorkerCount();
int obj_count = objects->size();
int batch_size = obj_count / thread_count;
int first_size = batch_size + obj_count % thread_count;
auto task = new data_transfer_task(0, first_size, this, this->mTm);
this->mTm->submitUnnamedTask(*task, physx::PxTaskType::TT_CPU);
task->removeReference();
if (batch_size > 0) {
for (int i = 1; i < thread_count; i++) {
task = new data_transfer_task(first_size + batch_size * (i - 1), first_size + batch_size * i, this, this->mTm);
this->mTm->submitUnnamedTask(*task, physx::PxTaskType::TT_CPU);
task->removeReference();
}
}
}
void data_transfer_task::run() { update_transforms(); }
I create start_transfer_task instance before call simulate, pass start_transfer_task to simulate, and i expect that start_transfer_task should run after all physx task done its own job, so write and read api calls dont owerlap, and calling fetchResults(block=true) continue execution only where all of my tasks finish copy transform data.
while (is_simulate) {
auto transfer_task = new start_transfer_task(gScene->getCpuDispatcher(), &objects, gScene->getTaskManager());
gScene->simulate(1.0f / 60.0f, transfer_task);
gScene->fetchResults(true);
//some other logic to call graphics api and sleep to sustain 30 updates per second
But i got many warnings about read and write api call owerlapping like this.
\physx\source\physx\src\NpWriteCheck.cpp (53) : invalid operation : Concurrent API write call or overlapping API read and write call detected during physx::NpScene::simulateOrCollide from thread 8492! Note that write operations to the SDK must be sequential, i.e., no overlap with other write or read calls, else the resulting behavior is undefined. Also note that API writes during a callback function are not permitted.
And, sometimes after start my app, i got a strange assert message.
physx\source\task\src\TaskManager.cpp(195) : Assertion failed: !mPendingTasks"
So, what i doing wrong ?
The concurrent API call warning is essentially telling you that you are calling for multiple thread PhysX API functions that are supposed to be single threaded.
Using the PhysX API you have to be very careful because it is not thread safe, and the thread safeness is left to the user.
Read this for more information.

Unknown reason for "ArgumentOutOfRangeException: Argument is out of range. Parameter name: index" exception

I am making a Unity game where the player is collecting data about aliens.
Therefor the player points on the alien and uses something like a camera.
Camera --> shoots Ray --> Ray returns all needed data attached to the script on the alien-gameobject
void ShootRay()
{
RaycastHit hitInfo; // stores information about hitted object
if (Physics.Raycast (transform.position, transform.forward, out hitInfo, maxRaycastRange, 1 << LayerMask.NameToLayer("creature"))) // out hitInfo = Unity puts information in the variable hitInfo
{
// UI alerts and collecting dna
if (hitInfo.distance <= photoRaycastRange)
{
distanceInfo.text = "scanning_genome";
if (hitInfo.collider.gameObject.GetComponent<EnemyAI> ().dna_collected == false) {
if (dna_percent_0_to_1 < 1)
{
calming_dna_scan_circle = false;
distanceInfo.text = "scanning_genome";
dna_percent_0_to_1 += Time.deltaTime * dna_scanSpeed;
dna_collect_circle.fillAmount = dna_percent_0_to_1;
}
else if (dna_percent_0_to_1 >= 1)
{
// adding info of creature to database
if (hitInfo.collider.gameObject.GetComponent<EnemyAI> ().raceIndex == 1)
{
if (!raceOneWasAdded)
{
BestiariumData.scannedSpecies.Add (hitInfo.collider.gameObject);
raceOneWasAdded = true;
}
BestiariumData.dnaBar_1 += 0.25f;
The mentioned database is simply a class called BestiariumData with:
public static List<GameObject> scannedSpecies = new List<GameObject> ();
public static List<float> savedDNAFillRates = new List<float> ();
public static float dnaBar_1 = 0;
public static float dnaBar_2 = 0;
public static float dnaBar_3 = 0;
public static float dnaBar_4 = 0;
public static float dnaBar_5 = 0;
public static float dnaBar_6 = 0;
public static float dnaBar_7 = 0;
public static float dnaBar_8 = 0;
}
I'm having a menu where the player can check which aliens he/she already has collected data. The name of the alien is displayed (Monster One, ...) and a progress bar for how many alien individuals the player has scanned.
THE PROBLEM:
if I try to assign the NAME of the status bar if throws the ArgumentOutOfRangeException: Argument is out of range. Parameter name: index exception. I am doing this by setting a bool in another script to true.
public List<GameObject> monsterButtons = new List<GameObject>();
public static bool nameButtons = false;
// Update is called once per frame
void LateUpdate ()
{
if (nameButtons)
{
for (int buttonIndex = monsterButtons.Count; buttonIndex > 0; buttonIndex--)
{
monsterButtons [buttonIndex].GetComponentInChildren<Text> ().text = BestiariumData.scannedSpecies [buttonIndex].name;
}
}
}
Thank you for your help.
Button index gives the count of your list. So say your list contains 10 items, count will be 10.
However a list's index starts at 0, not 1.
So when you try to access monsterButtons [buttonIndex] for the first time, you are calling index 10, which means item 11. This does not exist so throws your error.
To fix, add "-1" to your index asigning:
for (int buttonIndex = monsterButtons.Count -1; buttonIndex >= 0; buttonIndex--)
{
monsterButtons [buttonIndex].GetComponentInChildren<Text> ().text = BestiariumData.scannedSpecies [buttonIndex].name;
}

How to simulate digital logic circuits with feedback loops?

I learning how to simulate digital logic circuits .
I am presenting the source code of my first attempt here.
It is small program for simulating circuits consisting
of AND,OR and NOT gates.
This code works well for circuits without loops.
When circuit loops are introduced it causes a stack overflow because of endless recursion.
Please help me to remove this bug.
Please note that this is a hobby project and any help will be appreciated.
Source code :
#include <cstdlib>
#include <iostream>
using namespace std;
class LogicGate
{
int type;//gate type: 0 for NOT, 1 for OR, 2 for AND
//pins
bool ina;//input a
bool inb;//input b::this pin is not used for NOT gate
bool outc;//output
//fan-in
LogicGate* ga;//gate connected to input a
LogicGate* gb;//gate connected to input b
//fan-out
LogicGate* gc;//gate connected to output
int gctarget;//target input to which the gate "gc" is connected, 0 for input a, 1 for input c
public:
char* name;
LogicGate()
{
ina = inb = outc = false;
ga = gb = gc = (LogicGate*)0;
type = 0;
}
LogicGate(bool a, bool b)
{
ina = a; inb = b; outc = false;
ga = gb = gc = (LogicGate*)0;
type = 0;
}
//set logic
void settype(int t){if(t>=0&&t<3)type=t;else type=0;}
//set input
void seta(bool a){ ina = a; }
void setb(bool b){ inb = b; }
void setab(bool a, bool b){ina = a; inb = b; }
//connect gate
void cona(LogicGate* cga){ ga = cga; }
void conb(LogicGate* cgb){ gb = cgb; }
void conab(LogicGate* cga, LogicGate* cgb){ ga = cga; gb = cgb; }
//connect the output of this gate to another gate's input
void chainc(LogicGate* cgc, int target)
{
gc = cgc;
gctarget = target;
if(target==0) cgc->cona(this); else cgc->conb(this);
}
//calculate output
bool calcout()
{
//if the input is not available make it available by forcing the connected gates to calculate
if(ga){ ina = ga->calcout(); } //BUG:this may cause Stack overflow for circuits with loops
if(gb){ inb = gb->calcout(); }//BUG:this may cause Stack overflow for circuits with loops
//do the logic when inputs are available
switch(type)
{
case 0:
outc = !ina; break;
case 1:
outc = ina || inb; break;
case 2:
outc = ina && inb; break;
}
//if a gate is connected to output pin transfer the output value to the target input pin of the gate
if(gc){
if(gctarget==0){
gc->seta(outc);
}else{
gc->setb(outc);
}
}
//for debugging only
cout<<name<<" outputs "<<outc<<endl;
return outc;
}
};
int main(int argc, char *argv[])
{
LogicGate x,z;
//AND gate
z.settype(2);
z.seta(false);
z.setb(true);
z.name = "ZZZ";
//OR gate
x.settype(1);
x.cona(&z); // take one input from AND gate's output
x.setb(true);
x.name = "XXX";
//z.cona(&x);// take one input from OR gate's output to make a loop:: results in stack overflow
x.chainc(&z,0);//connect the output to AND gate's input "a" to form loop:: results in stack overflow
cout<<"final output"<<x.calcout()<<endl;
return 0;
}
The Problem here is that you are Looping infinitely. A program behaves somehow different than real logic gates. I see two possibilities here:
1) Implement cycles
You can implement it like a cpu works. a call to calcout only calculates to Output of one gate and iterates to the next one. You could create a Container class for your gates:
class GateContainer
{
//Contains all gates of your "circuit"
std::vector<LogicalGate> allGates;
//Contains all current gates to be processed
std::queue<LogicalGate*> currentGates;
void nextStep();
}
The nextStep function could look like this:
void GateContainer::nextStep()
{
//Get first gate from queue
LogicalGate *current = currentGates.front();
currentGates.pop();
//Do all the calculations with th current gate
//Push the gate connected to the Output to the list
currentGates.push(current->gc);
}
Please not that this code is untested and may also Need some error checks
2) Try to catch Loops
You can also try to catch Loops in calcout. You could achieve this by creating a flag in LogicalGate and reset it every time before calling calcout:
class LogicalGate
{
...
bool calculated;
...
}
Now before calling calcout() You Need to set calculated to false for every gate. Then, calcout could look something like this:
bool calcout()
{
calculated = true;
if(ga && !ga->calculated){ ina = ga->calcout(); }
if(gb && !ga->calculated){ inb = gb->calcout(); }
...
}

Creating object in C++ , what if already constructed?

I am still new to c++. I want to read in messages from several sources. Each source will begin data messages with a 4 char ID. Each will also have several data messages. No one message has all of the info I want from the device. So if I create an object with the ID as the object name, the next time a message is received, will the object be updated or completely reconstructed? Is there a way to check if the object is already constructed before calling it in the code?
class Channels{
public:
INT8U systemID; //0x01 Glonass, 0x02 GPS
INT8U satID;
INT8U GlonassNumber;
INT8U SNR; //signal to noise ratio
FP64 carrierPhase; //cylces
FP64 psuedoRange; //milliseconds
FP64 doppler; //HZ cycles
float tropDelay; //meters
float ionoDelay; //meters
};
class BaseStation{
public:
Channels channel[32]; //each channel object has all channel class variables in it
int numberSatelitesTracked;
FP64 timeUTC;
INT16U week;
FP64 GPStoUTCoffset;
FP64 GLOtoUTCoffset;
INT8S recieverTimeOffset;
FP64 posX; //geocentric coordinates in meters
FP64 posY;
FP64 posZ;
FP64 rmsX; //expected root mean square error of coordinates
FP64 rmsY;
FP64 rmsZ;
};
if( check == SOCKET_ERROR){
if( WSAGetLastError() != WSAEWOULDBLOCK){
printf("base station client recieve failed with error %d \n", WSAGetLastError());
FreeSocketInformation(i); //shuts down client socket if no data
}
continue;
}
else{
//recieve bytes into array
memcpy(recvArray, SocketInfo->DataBuf.buf, SocketInfo->RecvBytes +1);
//print recieved bytes on screen
printf("%s \n", SocketInfo->DataBuf.buf);
//first 4 bytes in message are base ID
cBuffer[0] = recvArray[0];
cBuffer[1] = recvArray[1];
cBuffer[2] = recvArray[2];
cBuffer[3] = recvArray[3];
baseID = cBuffer;
//create object with 4 char name
BaseStation baseID;
//test message identity and sort data
if(recvArray[4] == 0x10 && recvArray[5] == 0xF5){
baseID.timeUTC = combine64(recvArray[6]);
baseID.week = combine16u(recvArray[14]);
baseID.GPStoUTCoffset = combine64(recvArray[16]);
baseID.GLOtoUTCoffset = combine64(recvArray[24]);
baseID.recieverTimeOffset = recvArray[32];
int noChannels = (check-30) /30 ;
if (noChannels >= 32){
noChannels = 32;
}
int x = 33;
for(int m = 0; m < noChannels; m++){ //advance reading for channel m
baseID.channel[m].systemID = recvArray[x];
x++;
baseID.channel[m].satID = recvArray[x];
x++;
baseID.channel[m].GlonassNumber = recvArray[x];
x++;
baseID.channel[m].SNR = recvArray[x];
x++;
baseID.channel[m].carrierPhase = combine64(recvArray[x]);
x = x+8;
baseID.channel[m].psuedoRange = combine64(recvArray[x]);
x = x+8;
baseID.channel[m].doppler = combine64(recvArray[x]);
x = x+10;
} //end of for loop to gather F5 sat data
} //end F5 message data
if(recvArray[4] == 0x10 && recvArray[5] == 0xF6){
baseID.posX = combine64(recvArray[6]);
baseID.posY = combine64(recvArray[14]);
baseID.posZ = combine64(recvArray[22]);
baseID.rmsX = combine64(recvArray[30]);
baseID.rmsY = combine64(recvArray[38]);
baseID.rmsZ = combine64(recvArray[46]);
} //end F6 message data
OK so it seems an Array may be the best for me to use. So if I setup 100 base objects and then track the active array elements with a second boolean array, does this look like it should work? (baseID added to the base object)
BaseStation base[100];
boolean baseActive[100];
int baseNumber;
//begin message processing------------------------------------------------------------
//first 4 bytes in message are base ID
cBuffer[0] = recvArray[0];
cBuffer[1] = recvArray[1];
cBuffer[2] = recvArray[2];
cBuffer[3] = recvArray[3];
string name = cBuffer;
//check for existing baseID------------------------------------------------------------
// 100 array positions
//find if base is already in use, create new if not in use
for(baseNumber = 0; base[baseNumber].baseID != name; baseNumber++){
//for statement increases untill it finds baseID == name
if( baseNumber >= 100){ //baseID not currently in use
for(int n=0; baseActive[n] == true; n++){
//for statement increases untill finds a false baseActive
baseNumber = n; //assign baseNumber to the array position
base[baseNumber].baseID = name; //create new baseID
continue;
}
}
}
//check and process message data--------------------------------------------------------
if( base[baseNumber].baseID == name){
baseActive[baseNumber] = true;
//test message identity and sort data
}//end of for loop
//test connection, if no bytes recieved then connection is closed.----------------------
if( SocketInfo->RecvBytes == 0){
FreeSocketInformation(i); //shuts down client socket if no data
continue;
}
}
} //end of read data from socket
}
//need to add a timer to remove non sending bases from the baseActive[] array
C++ is a statically typed language, You need to provide the object name at compile time.
You cannot create an object name at run-time and create object with that name.
As already answered, you can't do so in C++.
However you can solve your problem in other way.
First, you need to bind some ID to some concrete object of structure BaseStation. You can provide this link in two ways - by holding BaseStation objects in associative containter, where keys are ID, or by holding array of BaseStation objects(as far as I can guess you are writing some sort of microcontroller code so std containers can be not available for you).
First approach code example:
//id is 4 char so it can be thought as int on most systems
std::map<int, BaseStation *> baseStations;
int * id = (int*)recvArray; //this hack is for showing how you can convert 4 char to int
//may be in your code (int id = combine32(recvArray[0])) is equvivalent
if(baseStations.find(*id) != baseStations.end()) //checking existance of object with such id
{
//ok, exists, do nothing
}
else
baseStations[*id] = new BaseStation(); //create new
baseStations[*id].timeUTC = combine64(recvArray[6]); //starting copying values
//other values copying
In second situation if you can't use associative containers or can't afford their libs\code because of microcontroller memory lack, you can use just arrays but it's not flexible at all and consumes more operations. Example:
//BaseConnection also holds field names id;
BaseConnection baseConnections[N];
int FindId(int id); //return index of element in baseConnections array with this id
BaseConnection * workingConnection = &baseConnections[FindId(combine32(recvArray[0]))];
workingConnection->timeUTC = combine64(recvArray[6]); //starting copying values
//other values copying

Segmentation fault occurs only under release configuration

For some odd reason, my application likes to break on me when I switch to release and run it outside of my debugger. Here's what works for me, and here's what doesn't
(Qt Creator is the IDE)
Debugging with debug configuration - ok
Running with debug configuration - ok
Debugging with release configuration - ok
Running with release configuration - application crash
My UI is one project, and the core for some stuff as a separate dependency. On Windows (compiling with MSVCC), I hit a menu button, which eventually calls down to a function. In that function, the app breaks on adding a new element to a vector. e.g:
str *x = new str();
str *y = new str();
/* ...set some of x & y's members... */
vector.push_back(x); // works fine
vector.push_back(y); // causes crash
If I comment out the line vector.push_back(y);, the app continues no problem until the app leaves the event scope (i.e. the end of OnMenuButtonClick). On OS X, it's similar to the issue of adding an element to a vector, except I have:
std::vector<foo *> SomeFunction()
{
std::vector<foo *> returningVector;
/* do stuff */
std::vector<foo *> goo = GetFooObjects();
for (int i = 0; i < goo.size(); i++)
{
returningVector.push_back(goo[i]); // breaks here
}
}
So what are some causes of this strange behavior without a debugger attached and not under debug configuration? I've checked to make sure all of my variables are initialized, so I'm stumped. If you want to view the code above, the first part can be located here, and the second part here. Please forgive anything you see as "bad", and if you have suggestions that you just can't contain, then please do message me on GitHub.
Edit:
I looked more into it, and found out exactly what's causing the problem, but don't know how to fix it. This is the function where my app crashes (on OS X):
vector<Drive *> Drive::GetFATXDrives( bool HardDisks )
{
vector<Drive *> Return;
if (HardDisks)
{
vector<DISK_DRIVE_INFORMATION> Disks = GetPhysicalDisks();
for (int i = 0; i < (int)Disks.size(); i++)
{
DISK_DRIVE_INFORMATION ddi = Disks.at(i);
// First, try reading the disk way
Streams::xDeviceStream* DS = NULL;
try
{
char path[0x200] = {0};
wcstombs(path, ddi.Path, wcslen(ddi.Path));
DS = new Streams::xDeviceStream(ddi.Path);
}
catch (xException& e)
{
continue;
}
if (DS == NULL || DS->Length() == 0 || DS->Length() < HddOffsets::Data)
{
// Disk is not of valid length
continue;
}
DS->SetPosition(HddOffsets::Data);
// Read the FATX partition magic
int Magic = DS->ReadInt32();
// Close the stream
DS->Close();
// Compare the magic we read to the *actual* FATX magic
if (Magic == FatxMagic)
{
Drive *d = new Drive(Disks.at(i).Path, Disks.at(i).FriendlyName, false);
Return.push_back(d);
}
}
}
vector<Drive *> LogicalDisks = GetLogicalPartitions();
for (int i = 0; i < (int)LogicalDisks.size(); i++)
{
Return.push_back(LogicalDisks.at(i));
}
return Return;
}
If I change if (HardDisks) to if (HardDisks = false), the app works just fine. So, I looked into that scope and discovered that after vector<DISK_DRIVE_INFORMATION> Disks = GetPhysicalDisks();, the heap gets corrupt or something like that. I noticed this because in the debugger, after that function is called, my HardDisks bool changes to "false", which wasn't what it was before.
Here is GetPhysicalDisks:
vector<Drive::DISK_DRIVE_INFORMATION> Drive::GetPhysicalDisks( void )
{
// RIGHT AFTER this vector is initialized, everything goes to hell
vector<Drive::DISK_DRIVE_INFORMATION> ReturnVector;
DIR *dir;
dirent *ent;
dir = opendir("/dev/");
if (dir != NULL)
{
// Read the shit
while ((ent = readdir(dir)) != NULL)
{
// Check the directory name, and if it starts with "disk" then keep it!
QRegExp exp("disk*");
exp.setPatternSyntax(QRegExp::Wildcard);
exp.setCaseSensitivity(Qt::CaseInsensitive);
if (exp.exactMatch(ent->d_name))
{
DISK_DRIVE_INFORMATION curdir;
memset(curdir.FriendlyName, 0, sizeof(curdir.FriendlyName));
memset(curdir.Path, 0, sizeof(curdir.Path));
char diskPath[0x50] = {0};
sprintf(diskPath, "/dev/r%s", ent->d_name);
mbstowcs(curdir.Path, diskPath, strlen(diskPath));
int device;
if ((device = open(diskPath, O_RDONLY)) > 0)
{
#ifdef __linux
hd_driveid hd;
if (!ioctl(device, HDIO_GET_IDENTITY, &hd))
{
swprintf(curdir.FriendlyName, strlen(hd) * 2, L"%hs", hd.model);
}
#elif defined __APPLE__
mbstowcs(curdir.FriendlyName, ent->d_name, strlen(ent->d_name));
#endif
ReturnVector.push_back(curdir);
}
}
}
}
return ReturnVector;
}
While this isn't a real answer as to what happened, I did find a way to fix the problem. Looking at my edit above, I edited my Drive::GetFATXDrives function like so:
vector<Drive *> Drive::GetFATXDrives( bool HardDisks )
{
// Initialize Disks vector up here
vector<DISK_DRIVE_INFORMATION> Disks;
// Call the function to get the hard disks
if (HardDisks)
Drive::GetPhysicalDisks(Disks);
vector<Drive *> ReturnVector;
if (HardDisks)
{
Streams::xDeviceStream* DS = NULL;
for (int i = 0; i < (int)Disks.size(); i++)
{
/* ... */
}
if (DS)
{
DS->Close();
delete DS;
}
}
vector<Drive *> LogicalDisks = GetLogicalPartitions();
for (int i = 0; i < LogicalDisks.size(); i++)
{
ReturnVector.push_back(LogicalDisks[i]);
}
return ReturnVector;
}
And my Drive::GetPhysicalDisks function now takes a vector<DISK_DRIVE_INFORMATION> reference instead of returning one. Seemed to make my program work just fine after that.