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);
Related
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);
I want to create an object on the device and allocate it to a pointer available on the host. Is there something I'm doing wrong in here?
__global__ void createAProduction(DeviceProduction* production) {
production = new AProduction();
}
DeviceProduction * devAProduction = NULL;
cudaMalloc(&devAProduction, sizeof(AProduction));
createAProduction<<<1, 1>>>(devAProduction);
deviceProductions["A"] = devAProduction;
Somewhere further in the code I'd like to do sth. like:
BatchOperation ** devBatchOperations;
cudaMalloc((void **) &devBatchOperations, sizeof(BatchOperation *) * operationCount);
Then I populate that pointer array with that:
void DeviceBatchExecutor::execute(vector<BatchOperation> operationsToPerform) {
BatchOperation ** devBatchOperations;
cudaMalloc((void **) &devBatchOperations, sizeof(BatchOperation *) * operationsToPerform.size());
int i = 0;
for(batchOperationIt it = operationsToPerform.begin(); it != operationsToPerform.end(); ++it) {
BatchOperation * devBatchOperation;
cudaMalloc(&devBatchOperation, sizeof(BatchOperation));
cudaMemcpy(&devBatchOperation, &it, sizeof(BatchOperation), cudaMemcpyHostToDevice);
Vertex * devInputNode = it->inputNode->allocateToDevice();
cudaMemcpy(&(devBatchOperation->inputNode), &devInputNode, sizeof(Vertex *), cudaMemcpyDeviceToDevice);
cudaMemcpy(&(devBatchOperation->production), &(it->production), sizeof(Production *), cudaMemcpyDeviceToDevice);
cudaMemcpy(&devBatchOperations[i], &devBatchOperation, sizeof(BatchOperation *), cudaMemcpyDeviceToDevice);
i++;
}
int operationCount = operationsToPerform.size();
executeOperations<<<operationCount, 1>>>(devBatchOperations);
}
where production is a pointer to the device memory holding that created object AProduction. Then I finally invoke processing via
executeOperations<<<operationCount, 1>>>(devBatchOperations);
So I'm relying on virtual method calls. As those DeviceProduction objects were created on the device, there is also a virtual pointer table so it should work. See example here. But it doesn't since the received batch operations seem random... crashes on invocation.
__global__ void executeOperations(BatchOperation ** operation) {
operation[blockIdx.x]->production->apply(operation[blockIdx.x]->inputNode);
}
Batch operation is a struct holding the production to be executed.
struct BatchOperation {
Production * production;
Vertex * inputNode;
Vertex * outputNode;
};
Is there something I'm doing wrong in here?
Yes, probably. The pointer production is passed to the kernel by value:
createAProduction<<<1, 1>>>(devAProduction);
It points to a location in device memory somewhere, since you've already run cudaMalloc on it. This line of kernel code:
production = new AProduction();
overwrites the pass-by-value copy of the production pointer with a new one, returned by in-kernel new. That is almost certainly not what you had intended. (And you haven't defined what AProduction is.). At the completion of that kernel call, the pass-by-value "copy" of the pointer will be lost anyway. You might be able to fix it like this:
*production = *(new DeviceProduction());
Now your production pointer points to a region in device memory that holds an instantiated (on the device) object, which appears to be your intent there. Creating a new object just to copy it may not be necessary, but that is not the crux of the issue I'm trying to point out here. You can probably also "fix" this issue by passing a pointer-to-pointer to the kernel instead. You would then need to allocate for an array of pointers, and assign one of the individual pointers using the in-kernel new directly, as you have shown.
The remainder of your code has a great many items undefined. For example in the above code it's not clear why you would declare that production is a pointer to a DeviceProduction type, but then try to allocate an AProduction type to it. Presumably that is some form of object inheritance which is unclear.
Since you haven't really provided anything approaching a complete code, I've borrowed some pieces from here to put together a complete worked example, showing object creation/setup in one kernel, followed by another kernel that invokes virtual methods on those objects:
$ cat t1086.cu
#include <stdio.h>
#define N 4
class Polygon {
protected:
int width, height;
public:
__host__ __device__ void set_values (int a, int b)
{ width=a; height=b; }
__host__ __device__ virtual int area ()
{ return 0; }
};
class Rectangle: public Polygon {
public:
__host__ __device__ int area ()
{ return width * height; }
};
class Triangle: public Polygon {
public:
__host__ __device__ int area ()
{ return (width * height / 2); }
};
__global__ void setup_f(Polygon ** d_polys) {
int idx = threadIdx.x+blockDim.x*blockIdx.x;
if (idx < N) {
if (idx%2)
d_polys[idx] = new Rectangle();
else
d_polys[idx] = new Triangle();
d_polys[idx]->set_values(5,12);
}};
__global__ void area_f(Polygon ** d_polys) {
int idx = threadIdx.x+blockDim.x*blockIdx.x;
if (idx < N){
printf("area of object %d = %d\n", idx, d_polys[idx]->area());
}};
int main () {
Polygon **devPolys;
cudaMalloc(&devPolys,N*sizeof(Polygon *));
setup_f<<<1,N>>>(devPolys);
area_f<<<1,N>>>(devPolys);
cudaDeviceSynchronize();
}
$ nvcc -o t1086 t1086.cu
$ cuda-memcheck ./t1086
========= CUDA-MEMCHECK
area of object 0 = 30
area of object 1 = 60
area of object 2 = 30
area of object 3 = 60
========= ERROR SUMMARY: 0 errors
$
Robert's suggestion seems to made it work:
__global__ void createAProduction(DeviceProduction** production) {
int idx = threadIdx.x+blockDim.x*blockIdx.x;
if(idx == 0) {
production[0] = new AProduction();
}
}
Called like this:
DeviceProduction ** devAProduction = NULL;
cudaMalloc(&devAProduction, sizeof(AProduction *));
createAProduction<<<1, 1>>>(devAProduction);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
But if I want to keep single pointer structure for deviceProductions array would it be ok to do sth. like this?
deviceProductions["A"] = (DeviceProduction *) malloc(sizeof(AProduction *));
gpuErrchk(cudaMemcpy(deviceProductions["A"], devAProduction, sizeof(AProduction *), cudaMemcpyDeviceToHost));
My intention was to copy the pointer (address) to the host memory from the device memory. Am I doing it right?
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 cannot figure out why g++ is giving the following errors. I believe that all the function are declared properly and the braces match up.
(testHashT.cpp just has the header and an empty main)
USERNAME#SERVER 391> g++ -Wall -pthread testHashT.cpp -o testHashT
memHashT.h:22: error: invalid function declaration
memHashT.h: In function âvoid memAccessUpdate(void*, unsigned int, pthread_t, bool)â:
memHashT.h:78: error: âgetHTElementâ was not declared in this scope
memHashT.h:88: error: âgetHTIndexâ was not declared in this scope
memHashT.h:93: error: cannot convert âlinkedMlist*â to âmList*â in assignment
memHashT.h:102: error: âcountWSâ was not declared in this scope
memHashT.h:107: error: âcountRAâ was not declared in this scope
memHashT.h: In function âmList* getHTElement(void*)â:
memHashT.h:133: error: âgetHTIndexâ was not declared in this scope
USERNAME#SERVER 389> cat memHashT.h
//Basic hash table for memory addresses, recommended size for program running is table indexed by a prime ~81281
/************************************************************
* Structure of table:
* Hash table indexed by memory address
* at each entry a vector made of arrays with size 2 of void pointers
* each vector entry will have the unique memory address and a pointer to a vector
* the vector it points to will contain a list of all threads that accessed that location
*
* Overall:(currently being changed to HT=>LL=>LL
* Hash Table => Vector => Vector Containing threads that accessed a given memory location
*************************************************************/
#include <pthread.h>//same as bellow
#include <stdlib.h>//watch out in case actual function contains this
//using namespace std;
//Global var
unsigned int tableSize; //note this is best if it is a prime number
unsigned long long countWA;
unsigned long long countRA:
unsigned long long countWS;
unsigned long long countRS;
//Linked Lists (thread, then mem)
//added all information in T_list to the M list, can be deleted
/*struct linkedT_list {
int threadID;
struct linkedT_list * nextT;
};
typedef struct linkedT_list tList;
tList * currT, * headT;*/
//For memory addresses
struct linkedM_list {
void * memAddr;
//Details
bool shared;
pthread_t prevThread;
unsigned long long rCounter;
unsigned long long wCounter;
//End Details
struct linkedMlist * nextM;
};
typedef struct linkedM_list mList;
//mList * currM, * headM;
mList ** hashTable;
//Create the hash table
int createHashTable(unsigned int num) {
tableSize = num;
hashTable = (mList **) malloc(sizeof(mList) * tableSize);
if (hashTable == NULL)
{
return 0;
//printf("Error: Memory could not be allocated");
}
else {
unsigned int i;
for(i=0;i<tableSize;i++)
{
hashTable[i]=NULL;
}
}
return 1;
}
void destroyHashTable(){
free(hashTable);
}
//adds a element to the hash table
void memAccessUpdate(void * memArg, unsigned int thread, pthread_t thread_id, bool writeAccess){
mList * headM = getHTElement(memArg);
mList * currM;
if (headM == NULL)
{//then create and new mList
currM = (mList *)malloc(sizeof(mList));
//initialize values
currM->shared = false;
currM->prevThread = thread_id;
currM->rCounter = 0;
currM->wCounter = 0;
currM->nextM = hashTable[getHTIndex(memArg)];
hashTable[getHTIndex(memArg)] = currM;
}
else {//change details in linked list and global var
//headM->nextM = (mList *)malloc(sizeof(mList));
currM = headM->nextM;
if (thread_id != currM->prevThread){
currM->shared = true;
currM->prevThread = thread_id;
}
if(writeAccess)
{
countWA++;
if(currM->shared){
countWS++;
}
currM->wCounter++;
}
else{//mem read
countRA++;
if(currM->shared){
countRS++;
}
currM->rCounter++;
}
}
//if (stuff) //possibly don't need
//else
// head = hashTable[index]; //note may be null
// curr = (mList *)malloc(sizeof(mList));
// curr->
}
//remove a element
void removeHTElement(void * memArg){
//note no garbage collection yet
;
}
//returns pointer to mList containing information
//NOT CORRECTLY IMPLEMENTED YET, NEED TO FIND RIGHT MEM ADDRESS, NOT JUST TOP MEM
mList * getHTElement(void * arg){
mList * tempM;
//tList * tempT = NULL;
unsigned int index = getHTIndex(arg);
tempM = hashTable[index];
//tempT = tempM->threadList;
return tempM;
}
//returns the number of threads to access a memery location
int tLength(void * arg){
return -1;
}
//computes the index of the hash table
//made its own function in case future implementation need to change how indexing is set up
unsigned int getHTIndex (void * arg){
return (unsigned int) ((unsigned long long)arg%tableSize);
}
You're using functions before you declare them. For example getHTElement uses getHTIndex which is not declared until afterwards.
In general, defining functions in headers is almost always wrong. Declare them in headers and define them in source files.
(You also have numerous errors in your testcase which tells me that the code you posted is not the code you're using, but it was enough to deduce the above.)
for(i=0;ishared = false;
This line is incomplete. In Vim, every following brace is red.
This line is almost certainly wrong:
hashTable = (mList **) malloc(sizeof(mList) * tableSize);
it is mList** so it should be sizeof(mList*) multiplied by a number, not sizeof(mList) multiplied by a number.
There is a clear syntax error here:
for(i=0;ishared = false;
as well as looking pointless because ishared=false in the evaluation section of for means the loop will never run anyway.
By the way why compile C code with g++?
I have a situation in Visual C++ 2008 that I have not seen before. I have a class with 4 STL objects (list and vector to be precise) and integers.
It has a method:
inline int id() { return m_id; }
The return value from this method is corrupt, and I have no idea why.
debugger screenshot http://img687.imageshack.us/img687/6728/returnvalue.png
I'd like to believe its a stack smash, but as far as I know, I have no buffer over-runs or allocation issues.
Some more observations
Here's something that puts me off. The debugger prints right values in the place mentioned // wrong ID.
m_header = new DnsHeader();
assert(_CrtCheckMemory());
if (m_header->init(bytes, size))
{
eprintf("0The header ID is %d\n", m_header->id()); // wrong ID!!!
inside m_header->init()
m_qdcount = ntohs(h->qdcount);
m_ancount = ntohs(h->ancount);
m_nscount = ntohs(h->nscount);
m_arcount = ntohs(h->arcount);
eprintf("The details are %d,%d,%d,%d\n", m_qdcount, m_ancount, m_nscount, m_arcount);
// copy the flags
// this doesn't work with a bitfield struct :(
// memcpy(&m_flags, bytes + 2, sizeof(m_flags));
//unpack_flags(bytes + 2); //TODO
m_init = true;
}
eprintf("Assigning an id of %d\n", m_id); // Correct ID.
return
m_header->id() is an inline function in the header file
inline int id() { return m_id; }
I don't really know how best to post the code snippets I have , but here's my best shot at it. Please do let me know if they are insufficient:
Class DnsHeader has an object m_header inside DnsPacket.
Main body:
DnsPacket *p ;
p = new DnsPacket(r);
assert (_CrtCheckMemory());
p->add_bytes(buf, r); // add bytes to a vector m_bytes inside DnsPacket
if (p->parse())
{
read_packet(sin, *p);
}
p->parse:
size_t size = m_bytes.size(); // m_bytes is a vector
unsigned char *bytes = new u_char[m_bytes.size()];
copy(m_bytes.begin(), m_bytes.end(), bytes);
m_header = new DnsHeader();
eprintf("m_header allocated at %x\n", m_header);
assert(_CrtCheckMemory());
if (m_header->init(bytes, size)) // just set the ID and a bunch of other ints here.
{
size_t pos = DnsHeader::SIZE; // const int
if (pos != size)
; // XXX perhaps generate a warning about extraneous data?
if (ok)
m_parsed = true;
}
else
{
m_parsed = false;
}
if (!ok) {
m_parsed = false;
}
return m_parsed;
}
read_packet:
DnsHeader& h = p.header();
eprintf("The header ID is %d\n", h.id()); // ID is wrong here
...
DnsHeader constructor:
m_id = -1;
m_qdcount = m_ancount = m_nscount = m_arcount = 0;
memset(&m_flags, 0, sizeof(m_flags)); // m_flags is a struct
m_flags.rd = 1;
p.header():
return *m_header;
m_header->init: (u_char* bytes, int size)
header_fmt *h = (header_fmt *)bytes;
m_id = ntohs(h->id);
eprintf("Assigning an id of %d/%d\n", ntohs(h->id), m_id); // ID is correct here
m_qdcount = ntohs(h->qdcount);
m_ancount = ntohs(h->ancount);
m_nscount = ntohs(h->nscount);
m_arcount = ntohs(h->arcount);
You seem to be using a pointer to an invalid class somehow. The return value shown is the value that VS usually uses to initialize memory with:
2^32 - 842150451 = 0xCDCDCDCD
You probably have not initialized the class that this function is a member of.
Without seeing more of the code in context.. it might be that the m_id is out of the scope you expect it to be in.
Reinstalled VC++. That fixed everything.
Thank you for your time and support everybody! :) Appreciate it!