I have this multiset container:
multiset<IMidiMsgExt, IMidiMsgExtComp> queuedNotes;
IMidiMsgExt is a struct I've created myself (I need it for one additional property, mTick) that extend IMidiMsg :
struct IMidiMsgExt : public IMidiMsg
{
IMidiMsgExt() {
}
double mTick = 0.;
void IMidiMsgExt::MakeNoteOnMsg(int noteNumber, int velocity, int offset, double tick, int channel)
{
Clear();
mStatus = channel | (kNoteOn << 4);
mData1 = noteNumber;
mData2 = velocity;
mOffset = offset;
mTick = tick;
}
void IMidiMsgExt::MakeNoteOffMsg(int noteNumber, int offset, double tick, int channel)
{
Clear();
mStatus = channel | (kNoteOff << 4);
mData1 = noteNumber;
mOffset = offset;
mTick = tick;
}
void IMidiMsgExt::Clear()
{
mOffset = 0;
mStatus = mData1 = mData2 = 0;
mTick = 0.;
}
};
Next: I store in that queuedNotes multiset some IMidiMsgExt objects, with:
IMidiMsgExt* noteOff = new IMidiMsgExt;
noteOff->MakeNoteOffMsg(57, 0, tickSize * 111, 0);
queuedNotes.insert(*noteOff);
Now, I need to use a function called SendMidiMsg(IMidiMsg* pMsg) (that takes IMidiMsg type as input) sending my object IMidiMsgExt to it.
I extract the first object from my list to an iterator:
auto midiMessage = queuedNotes.begin();
But when I try to cast it and use SendMidiMsg:
SendMidiMsg((IMidiMsgExt*)midiMessage);
it says no suitable conversion function from "std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<IMidiMsgExt>>>" to "IMidiMsg *" exists
Where am I wrong? Should I use dynamic casting?
auto midiMessage = queuedNotes.begin();
midiMessage is of type std::multiset::iterator. And it is not convertable to your type IMidiMsgExt. Iterator is an object that behaves similarly to a pointer, so you can use dereference operator (*) to get the object that it "points to". You also don't need to cast derived object to its base, that is done implicitly. All you need to do is get the address of where the iterator "points to" to get a pointer to IMidiMsgExt:
SendMidiMsg(&*midiMessage);
A quick break down of &*midiMessage:
variable - type
midiMessage - std::multiset::iterator
*midiMessage - IMidiMsgExt
&*midiMessage - IMidiMsgExt*
Edit:
About your const_iterator error. std::multiset::begin() is supposed to always return const_iterator. Your function SendMidiMsg() wants a non const pointer - it is saying it wants to edit the message. multiset does not allow changing the elements.
You can copy the message and then call SendMidiMsg(). If you don't need the message inside the container anymore, you can also erase it afterwards.
auto msg = *midiMessage;
SendMidiMsg(&msg);
queuedNotes.erase(midiMessage);
Note: It seems like you have a memory leak in the program. You create messages with new and I don't see any calls to delete, to release the memory.
IMidiMsgExt* noteOff = new IMidiMsgExt;
noteOff->MakeNoteOffMsg(57, 0, tickSize * 111, 0);
queuedNotes.insert(*noteOff);
Related
I've been trying for a long time to pass an array of objects to another class object.
In settingUp.cpp:
//** Status classes and their functions **//
void settingUp(){
dataClass prueba0;
dataClass prueba1;
dataClass prueba2;
const dataClass * arrayPrueba[3];
prueba0.setValues(1);
prueba1.setValues(2);
prueba2.setValues(3);
arrayPrueba[0] = &prueba0;
arrayPrueba[1] = &prueba1;
arrayPrueba[2] = &prueba2;
statusClass status;
status.setValues(1, arrayPrueba);
status.printValues();
}
In classData.cpp:
//** dataClass and their functions **//
void dataClass::setValues(int _length){
length = _length;
}
void dataClass::printValues() const{
printf("TP: dataClass: length = %d\n", &length);
};
In statusClass.cpp:
//** Status classes and their functions **//
void statusClass::setValues (uint8_t _statusSelectorByte, const dataClass **_array){
newStatusSelectorByte = _statusSelectorByte;
array = *_array;
};
void statusClass::printValues(){
printf("TP: statusClass -> printValues: Prueba = %d\n", newStatusSelectorByte);
printf("TP: statusClass -> printValues: arrayPrueba = %d\n", array[1].length);
}
When I call:
status.printValues();
I can read only the fist element of the arrayPrueba.
In statusClass::setValues(), *_array is the same as _array[0]. You are storing only the first dataClass* pointer from the input array.
Later, when using array[1], you are mistreating array as-if it were a pointer to an array of objects, when it is really a pointer to a single object instead. You are thus reaching past that object into surrounding memory, which is undefined behavior (but may "work" in this case because an object may happen to actually exist at that location, but this is bad behavior to rely on).
You need to store the original array pointer, not a single element taken from the array.
private:
const dataClass **array; // <-- add an *
void statusClass::setValues (uint8_t _statusSelectorByte, const dataClass **_array){
newStatusSelectorByte = _statusSelectorByte;
array = _array; // <-- get rid of the *
};
void statusClass::printValues(){
printf("TP: statusClass -> printValues: Prueba = %d\n", newStatusSelectorByte);
printf("TP: statusClass -> printValues: arrayPrueba = %d\n", array[1]->length); // use -> instead of .
}
On a side note: in dataClass::printValues(), you need to drop the & when printing the value of length:
printf("TP: dataClass: length = %d\n", length);
I'm new to C++ and I'm trying to dry up my code, for example:
void gethit () {
Gert.hitbox(AA.x, AA.damage);
Gert.hitbox(AB.x, AB.damage);
Gert.hitbox(AC.x, AC.damage);
Gert.hitbox(AD.x, AD.damage);
Gert.hitbox(Terbil.x, Terbil.damage);
}
AA, AB, AC, AD and Terbil are all instances of a class called Entity with variables x and damage.
Every time I want to add a new instance I'll have to come into this function and add it manually. I'm trying to add all of the address of the instances to an array like so:
void * p_enemys[10];
p_enemys[0] = &AA;
p_enemys[1] = &AB;
p_enemys[2] = &AC;
p_enemys[3] = &AD;
p_enemys[4] = &Terbil;
Just wondering how I could call a function from the instance via the array, I tried to do
for(int i = 0; i < 10; i++;) {
Gert.hitbox(p_enemys[i].x, p_enemys[i].damage);
}
and g++ compiler spits out: "request for member `damage' in `p_enemys[i]', which is of non-aggregate type `void *'"
I don't really need to use arrays specifically any help is very appreciated.
Changes made, thanks #gldraphael!
vector <Entity*> p_Enemys(10);
void gethit () {
for (int i = 0; i < 10; ++i) {
Entity * ienemy = (Entity*) p_Enemys[i];
Gert.hitbox((ienemy->x), (ienemy->damage));
}
}
You can make an a std::vector as follows:
std::vector <Entity*> p_Enemys(10);
The assigning part remains the same:
p_enemys[0] = &AA;
p_enemys[1] = &AB;
p_enemys[2] = &AC;
p_enemys[3] = &AD;
p_enemys[4] = &Terbil;
You can then loop through the p_enemys as follows:
for(auto i : p_enemys) {
Gert.hitbox(i->x, i->damage);
}
So what was it that you missed?
The array was declared as an array of void*
So, in the loop, p_enemys[i] returned a void*.
Also class/struct members are accessed using a dereferencing operator ->. You used the membership operator . instead.
So this code should have worked instead:
for(int i = 0; i < p_enemys.size(); i++;) { //
Entity * ienemy = (Entity*) p_enemys[i]; // cast the void* into a Entity*
Gert.hitbox(ienemy->x, ienemy->damage);
}
As a general rule, avoid void*s whenever possible.
I am facing a problem while creating an array of derived class objects, and I can not find any explanation of this problem. The problem is the following:
I have an abstract base class RDMonitorBase and a derived class RDMonitorHashTable.
In another class RDMonitorPool I have the variable RDMonitorBase * m_rd_monitors.
In RDMonitorPool constructor I am creating an array of RDMonitorHashTable objects (using new)
and assigning them to m_rd_monitors.
Immediately after the construction, only the even number indexed RDMonitorHashTable objects are properly formed. The objects with odd numbered index have garbage in the member variables. I have no idea why this is happening.
The code and the GDB output on a breakpoint immediately after the construction are given below:
Relevant parts of the RDMonitorBase and RDMonitorHashTable classes are as follows. I have a virtual Access() method in Base which is not implemented in the derived, and a pure virtual RecordDistance() method. Access() calls the RecordDistance() method. This should be okay I think, a similar structure worked when I created simple examples.
class RDMonitorBase {
public:
RDMonitorBase();
virtual void StartMonitoring(const physical_address_t& target_address, const int core_id);
virtual Index Access(const physical_address_t& address, const int core_id);
bool IsActive() { return m_active; }
static const Index TRACKING_NOT_COMPLETE = -1;
protected:
virtual void RecordDistance(const physical_address_t& address) = 0;
const Index m_maximum_distance;
bool m_active;
physical_address_t m_target_address;
Index m_distance;
int m_core_id;
};
class RDMonitorHashTable: public RDMonitorBase {
public:
RDMonitorHashTable();
virtual void StartMonitoring(const physical_address_t& target_address,
const int core_id);
protected:
virtual void RecordDistance(const physical_address_t& address);
std::tr1::unordered_set<physical_address_t> m_address_set;
};
RDMonitorBase::RDMonitorBase():
m_maximum_distance(32),
m_active(false),
m_target_address(0),
m_distance(0),
m_core_id(-1) { ; }
Index RDMonitorBase::Access(const physical_address_t& address,
const int core_id) {
// ... some code
RecordDistance(address);
//... some other code
return m_distance;
}
RDMonitorHashTable::RDMonitorHashTable()
:RDMonitorBase() { ; }
void RDMonitorHashTable::RecordDistance(const physical_address_t& address) {
m_address_set.insert(address);
m_distance = m_address_set.size();
}
Now in the RDMonitorPool class constructor, the following is basically executed:
RDMonitorBase * m_rd_monitors = new (std::nothrow) RDMonitorHashTable[4096];
After this line executes, when I try to print the objects in gdb, I get this:
(gdb) print *(m_rd_monitors + 0)
$2 = {_vptr.RDMonitorBase = 0x7ffd93cacc90, static TRACKING_NOT_COMPLETE = -1, m_maximum_distance = 32, m_active = false, m_target_address = 0, m_distance = 0, m_core_id = -1}
(gdb) print *(m_rd_monitors + 1)
$3 = {_vptr.RDMonitorBase = 0x1, static TRACKING_NOT_COMPLETE = -1, m_maximum_distance = 68540736, m_active = 11, m_target_address = 0, m_distance = 4611686019492741120, m_core_id = 11}
(gdb) print *(m_rd_monitors + 2)
$4 = {_vptr.RDMonitorBase = 0x7ffd93cacc90, static TRACKING_NOT_COMPLETE = -1, m_maximum_distance = 32, m_active = false, m_target_address = 0, m_distance = 0, m_core_id = -1}
(gdb) print *(m_rd_monitors + 3)
warning: can't find linker symbol for virtual table for `RDMonitorBase' value
$5 = warning: can't find linker symbol for virtual table for `RDMonitorBase' value
{_vptr.RDMonitorBase = 0x7ffda46b3e98, static TRACKING_NOT_COMPLETE = -1, m_maximum_distance = 68566480, m_active = 11, m_target_address = 0, m_distance = 4611686019492741120, m_core_id = 11}
So the even-indexed values have the proper values that are assigned in the constructor (for example 32 for m_maximum_distance). But the odd-index objexxts have garbage in m_maximum_distance and other members.
I will be extremely thankful if anybody can shed some light on why this is happening. Thanks!
Your problem is addressed here: Base pointer to array of derived objects
The problem is that the array is of type RDMonitorBase, so when you try to access any of its positions, the compiler calculates the offset according to RDMonitorBase instead of RDMonitorHashTable, effectively dereferencing the memory at the wrong point and thus slicing up the actual object which is of a different type. From the point your program access any position of that array, its bahavior becomes undefined.
The most straightforward alternative would be to use an array of pointers to the base type and assign an object of the derived class dynamicaly constructed to each of them.
RDMonitorBase* m_rd_monitors[4096];
for(std::size_t i = 0; i < 4096; ++i)
m_rd_monitors[i] = new (std::nothrow) RDMonitorHashTable;
Iam new to using Core Foundations. I want to use dictionary to store some key value pair. The value must be a pointer to a struct. This pointer is pointing to dynamically allocated buffer.
CFMutableDictionaryRef init_hash_table() {
return CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
This is used to create the dictionary and the return value is stored as global variable.
CFNumberRef
create_hash_key(int sd) {
return CFNumberCreate(NULL, kCFNumberIntType, &sd);
}
int
add_hash_entry(CFMutableDictionaryRef dict, int sd, void *pkt) {
CFNumberRef key = create_hash_key(sd);
CFDictionarySetValue(dict, key, pkt);
return 0;
}
When I execute this code, I get segfault. I see that pkt has a valid address and key seems to be created. Does anyone know how to assign a pointer to value part?
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000011
0x00007fff8c9f339f in objc_msgSend_fixup ()
Any ideas?
The problem is the kCFTypeDictionaryValueCallBacks argument. From the documentation:
kCFTypeDictionaryValueCallBacks
Predefined CFDictionaryValueCallBacks structure containing a set of
callbacks appropriate for use when the values in a CFDictionary are
all CFType-derived objects.
So in your case, CFRetain() is called on the pointer when the value is added to the
dictionary. This causes the crash because the pointer does not point to a CoreFoundation
object.
You can create the dictionary with
CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
instead, so that no "reference counting" will be done on the value.
Alternatively, you can wrap the pointer into a CFDataRef and put that into the
dictionary.
In both cases it is your responsibility that the pointer is still valid
when the value is retrieved from the dictionary later.
Here is a simple example how you could implement refcounting for your custom objects:
typedef struct {
int refcount;
int val;
} mystruct;
const void *myretain(CFAllocatorRef allocator, const void *value)
{
mystruct *p = (mystruct *)value;
p->refcount++;
return p;
}
void myrelease(CFAllocatorRef allocator, const void *value)
{
mystruct *p = (mystruct *)value;
if (p->refcount == 1)
free(p);
else
p->refcount--;
}
int main(int argc, const char * argv[])
{
mystruct *p = malloc(sizeof(*p));
p->refcount = 1;
p->val = 13;
CFDictionaryValueCallBacks vcb = { 0 , myretain, myrelease, NULL, NULL };
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &vcb);
int sd = 13;
CFNumberRef key = CFNumberCreate(NULL, kCFNumberIntType, &sd);
CFDictionarySetValue(dict, key, p);
// refcount == 2
myrelease(NULL, p);
// refcount == 1
mystruct *q = CFDictionaryGetValue(dict, key);
// refcount is still 1, "GetValue" does not increment the refcount
CFRelease(dict);
// object is deallocated
return 0;
}
I think I'm making just a fundamental mistake, but I cannot for the life of me see it.
I'm calling a method on an Objective-C object from within a C++ class (which is locked). I'm using NSInvocation to prevent me from having to write hundreds methods just to access the data in this other object.
These are the steps I'm going through. This is my first call, and I want to pass s2. I can't really provide a compilable example, but hopefully it's just a DUHRRRRR problem on my part.
float s2[3];
id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&s2};
_view->_callPixMethod(#selector(convertPixX:pixY:toDICOMCoords:),3,args2s);
This is the View method being called
invokeUnion View::_callPixMethod(SEL method, int nArgs, id args[])
{
DataModule* data;
DataVisitor getdata(&data);
getConfig()->accept(getdata);
invokeUnion retVal;
retVal.OBJC_ID = data->callPixMethod(_index, _datasetKey, method, nArgs, args);
return retVal;
}
Invoke Union is a union so I can get the float value returned by NSInvocation.
union invokeUnion {
id OBJC_ID;
int intValue;
float floatValue;
bool boolValue;
};
This is the method in the data Object (pthread locked with lock() and unlock());
id DataModule::callPixMethod(int index, std::string predicate, SEL method, int nArgs, id args[] )
{
// May Block
DCMPix *pix =[[getSeriesData(predicate) pix] objectAtIndex:index];
lock();
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMethodSignature *signature;
NSInvocation *invocation;
signature = [DCMPix instanceMethodSignatureForSelector:method];
invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:method];
[invocation setTarget:pix];
if (nArgs > 0) for (int n = 0; n < nArgs; n++) {
SFLog(#"invocation: i=%d, *ptr=0x%x, valf=%f, vald=%d",n,args[n],*args[n],*args[n]);
[invocation setArgument:args[n] atIndex:2+n];
}
id retVal;
[invocation invoke];
[invocation getReturnValue:&retVal];
[pool release];
unlock();
return retVal;
}
The method in the DCMPix object (which I can't modify, it's part of a library) is the following:
-(void) convertPixX: (float) x pixY: (float) y toDICOMCoords: (float*) d pixelCenter: (BOOL) pixelCenter
{
if( pixelCenter)
{
x -= 0.5;
y -= 0.5;
}
d[0] = originX + y*orientation[3]*pixelSpacingY + x*orientation[0]*pixelSpacingX;
d[1] = originY + y*orientation[4]*pixelSpacingY + x*orientation[1]*pixelSpacingX;
d[2] = originZ + y*orientation[5]*pixelSpacingY + x*orientation[2]*pixelSpacingX;
}
-(void) convertPixX: (float) x pixY: (float) y toDICOMCoords: (float*) d
{
[self convertPixX: x pixY: y toDICOMCoords: d pixelCenter: YES];
}
It's crashing when it tries to access d[0]. BAD_EXC_ACCESS which I know means it's accessing released memory, or memory outside of it's scope.
I'm getting lost keeping track of my pointers to pointers. the two float values come across fine (as does other info in other methods) but this is the only one asking for a float* as a parameter. From what I understand the convertPixX: method was converted over from a C program written for Mac OS 9... which is why it asks for the c-array as an out value... I think.
Anyway, any insight would be greatly appreciated.
I've tried sending the value like this:
float *s2 = new float[3];
void* ps2 = &s2;
id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&ps2};
_view->_callPixMethod(#selector(convertPixX:pixY:toDICOMCoords:),3,args2s);
But that gives a SIGKILL - plus I'm sure it's bogus and wrong. ... but I tried.
anyway... pointers! cross-language! argh!
Thanks,
An array is not a pointer. Try adding the following line
NSLog(#"%p, %p", s2, &s2);
just above.
id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&s2};
s2 and &s2 are both the address of the first float in your array, so when you do:
[invocation setArgument:args[n] atIndex:2+n];
for n = 2, you are not copying in a pointer to the first float, but the first float, possibly the first two floats if an id is 64 bits wide.
Edit:
To fix the issue, this might work (not tested).
float s2[3];
float* s2Pointer = s2;
id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&s2Pointer};
_view->_callPixMethod(#selector(convertPixX:pixY:toDICOMCoords:),3,args2s);
s2Pointer is a real pointer that will give you the double indirection you need.