I am trying to use a function provided in 3rd party documentation and am having trouble getting my head around it. I recently figured out the meaning of IN/OUT variables and how to work with them. The problem with this function is it has several different types all combined. I am really confused how to access these array elements. Provided below is a screenshot of the function information.
This is the code I am working with:
BYTE numDevices = 10;
BYTE devices;
ULONG devicesArray = QCWWAN2kEnumerateDevices(&numDevices,&devices);
//How do I access the elements in the returned array?
ULONG IS THE RETURN CODE TO SEE IF IT FAILED/WHY
You need to get a debugger on it. It is unclear whether the QCWWAN2kEnumerateDevices allocates memory for your devices. If it doesn't (I doubt it does, knowing Win32API) your
BYTE devices;
should instead be
struct DEVICE_ARRAY_ELEM {
char devID[256];
char devKey[16];
};
DEVICE_ARRAY_ELEM *pDevices = malloc(sizeof(DEVICE_ARRAY_ELEM) * 10);
ULONG devicesArray = QCWWAN2kEnumerateDevices(&numDevices, (pDevices);
//Do stuff
free((void *)pDevices);
EDIT___ sorry that was C, here it is in C++
struct DEVICE_ARRAY_ELEM {
char devID[256];
char devKey[16];
};
DEVICE_ARRAY_ELEM *pDevices = new DEVICE_ARRAY_ELEM[10];
ULONG devicesArray = QCWWAN2kEnumerateDevices(&numDevices, pDevices);
//do stuff
delete [] pDevices;
To access use:
pDevices[devnum].devID[IDIndex];
Improving upon John Silver's answer
// IN A HEADER:
typedef struct DEVICE_ARRAY_ELEM {
char devID[256];
char devKey[16];
} DEVICE_ARRAY_ELEM; // This defines a struct to hold the data brought back
// it also type defs 'struct DEVICE_ARRAY_ELEM' to 'DEVICE_ARRAY_ELEM' for convienence
// IN YOUR CODE:
// This pointer should be wrapped in a auto_ptr to help with RAII
DEVICE_ARRAY_ELEM *pDevices = new DEVICE_ARRAY_ELEM[10]; // allocate 10 elements in-line
ULONG errorCode = QCWWAN2kEnumerateDevices(&numDevices, (BYTE*)pDevices); // get them
// Here is the hard part: iterating over the array of devices returned
// as per the spec numDevices is now the number of devices parsed
for(int i = 0; i < numDevices; i++) {
printf("%s\n", pDevices[i].devID); // is the name of the device (a character array)
}
delete [] pDevices;
EDIT
I now use numDevices do iterate over the array since the spec says that is the number of devices enumerated after the function call
EDIT AGAIN
Here is the code working based on my assumptions: IDEONE
The code has some typedefs and a definition of what I think the QCWWAN2kEnumerateDevices operates. So those should be ignored, but the code is compiles and performs as expected
Related
I have a union (ValueDefinition) with pointers of different datatypes in it and functions to create it. With String it works fine:
ValueDefinition CreateValDefString(String value){
ValueDefinition valDef = {.ValueString = new String(value)};
return valDef;
}
But when I do the same with e.g. uint8_t it compiles, but at runtime I get this error:
[E][WString.cpp:185] changeBuffer(): realloc failed! Buffer unchanged
That's the code for the uint8_t:
ValueDefinition CreateValDefUint8(uint8_t value){
ValueDefinition valDef = {.ValueUInt8 = new uint8_t(value)};
return valDef;
}
What am I doing wrong? I tried it without "new" and with malloc, but I still get the same error.
Edit: As requested, the definition of ValueDefinition:
union ValueDefinition{
bool* ValueBool;
int8_t* ValueInt8;
int16_t* ValueInt16;
int32_t* ValueInt32;
uint8_t* ValueUInt8;
uint16_t* ValueUInt16;
uint32_t* ValueUInt32;
float* ValueFloat;
ulong* ValueULong;
String* ValueString;
};
In your code, it looks like C++ is throwing an error to a function to create a WString instead of uint8_t, hence the stacktrace in a completely separate header. Searching the source code in the repository for arduino shows that there is an error in WString.cpp here, which is what your compiler's detecting.
The github users suggest using a different string library, and since the bug hasn't been fixed you'll have to change, probably to the standard string library defined by C++ and not arduino. As the users have stated on github, arduino strings are notoriously unreliable.
In other words, this error has nothing to do with your code, but a question that I'd like to ask is "Why use unions in C++?" If you want to define a generic type just use templates, ex:
template<class T>
class ValueDefinition<T> {
private:
T typeDat;
public:
Valuedefinition(T t);
/* etc. */
}
Unions were made so that C could have a way to use generic typing by having several types share the data in the union. Another common use is taking advantage of the data types using the same memory to find the underlying binary of more complex types, such as using individual uint8_t values underlying a long long to find the value of its bits or using an int to get the binary value of a float, ex:
union foo {
uint8_t bits[4]; /* Represent the bits of 'data' */
long long int data;
}
union foo myLong = {.data = 12378591249169278l};
printf("%d\n", myLong.bits[0]); // Returns the value of the high bit of myLong
However note that this is undefined behavior because unions are usually padded and architectures use a different form of endianess. Whatever you're doing, if you're using C++ there's a better way to implement your solution than using unions, since this was a feature meant for a language that had no generic typing in order to save memory.
Edit:
Initialize ValueDefinition using C's malloc like so:
union ValueDefinition *value = malloc(sizeof(union ValueDefinition));
value->ValueUInt8 = malloc(sizeof(uint8_t));
/* more code */
Or with C++'s new:
union ValueDefinition *value = new ValueDefinition();
value->ValueUInt8 = new uint8_t(/* Some number */);
/* more code */
I'm searching for an example or explanation why someone should (or should not) use triple-pointers in C/C++.
Are there any examples where triple-pointer arise?
I am especially looking for source-code which uses triple-pointers.
The best example that comes to mind is a sparse multi-level table. For instance one way to implement properties for Unicode characters might be:
prop_type ***proptable;
...
prop_type prop = proptable[c>>14][c>>7&0x7f][c&0x7f];
In this case proptable would need to have a triple-pointer type (and possibly quadruple pointer if the final resulting type is a pointer type). The reason for doing this as multiple levels rather than one flat table is that, at the first and second levels, multiple entries can point to the same subtable when the contents are all the same (e.g. huge CJK ranges).
Here's another example of a multi-level table that I implemented; I can't say I'm terribly proud of the design but given the constraints the code has to satisfy, it's one of the least-bad implementation choices:
http://git.musl-libc.org/cgit/musl/tree/src/aio/aio.c?id=56fbaa3bbe73f12af2bfbbcf2adb196e6f9fe264
If you need to return an array of pointers to variable length strings via a function parameter:
int array_of_strings(int *num_strings, char ***string_data)
{
int n = 32;
char **pointers = malloc(n * sizeof(*pointers));
if (pointers == 0)
return -1; // Failure
char line[256];
int i;
for (i = 0; i < n && fgets(line, sizeof(line), stdin) != 0; i++)
{
size_t len = strlen(line);
if (line[len-1] == '\n')
line[len-1] = '\0';
pointers[i] = strdup(line);
if (pointers[i] == 0)
{
// Release already allocated resources
for (int j = 0; j < i; j++)
free(pointers[j]);
free(pointers);
return -1; // Failure
}
}
*num_strings = i;
*string_data = pointers;
return 0; // Success
}
Compiled code.
If you use a linked list you have to store the address of the first element of the list ( first pointer ) .
If you need to change in that list you need another pointer ( two pointer)
If you need to pass your list that you are changing in two pointers and change it in another function you need another pointer ( three pointer )...
They are a lots of examples
I've used triple pointers in C++:
There is an interface written for a Java program:
https://github.com/BenLand100/SMART/blob/master/src/SMARTPlugin.h
and it takes an array of strings.
typedef void (*_SMARTPluginInit)(SMARTInfo *ptr, bool *replace, int *buttonc, char ***buttonv, int **buttonid, _SMARTButtonPressed *buttonproc);
Then in my program I do:
char* btnTexts[2] = {"Disable OpenGL_Enable OpenGL", "Enable Debug_Disable glDebug"}; //array of C-style strings.
void SMARTPluginInit(SMARTInfo* ptr, bool* ReplaceButtons, int* ButtonCount, char*** ButtonTexts, int** ButtonIDs, _SMARTButtonPressed* ButtonCallback)
{
*ButtonText = btnTexts; //return an array of strings.
}
but in C++, you can use a reference instead of pointer and it'd become:
void SMARTPluginInit(SMARTInfo* ptr, bool* ReplaceButtons, int* ButtonCount, char** &ButtonTexts, int** ButtonIDs, _SMARTButtonPressed* ButtonCallback)
{
ButtonText = btnTexts; //return an array of strings.
}
Notice now that "ButtonTexts" is a reference to an array of C-style strings now.
A char*** can be a pointer to an array of C-style strings and that's one time that you'd use it.
A very simple example is a pointer to an array of arrays of arrays.
Triple pointer is a pointer variable that points to a pointer which in turn points to another pointer. The use of this complex programming technique is that usually in which companies process tons and tons of data at one time .A single pointer would point to a single block of data (suppose in a large file) using the triple pointer would result in 3 times faster processing as different blocks of data(in the same file) can be pointed by different pointer and thus data could be accessed/processed faster (unlike 1 pointer going through the whole file).
I am working on a test which checks if all class attributes are initialized in a constructor.
My current solution works for non pointer attributes:
void CSplitVectorTest::TestConstructorInitialization()
{
const size_t memorySize = sizeof(CSplitVector);
char* pBuffer1 = (char*) malloc(memorySize);
char* pBuffer2 = (char*) malloc(memorySize);
memset(pBuffer1,'?',memorySize);
memset(pBuffer2,'-',memorySize);
new(pBuffer1) CSplitVector;
new(pBuffer2) CSplitVector;
const bool bObjectsAreEqual = memcmp(pBuffer1,pBuffer2,memorySize)==0;
if (!TEST(bObjectsAreEqual))
{
COMMENT("Constructor initialization list not complete!");
}
free(pBuffer1);
free(pBuffer2);
}
Do you have an idea how could it be improved to test if pointers are initialized?
Your test checks whether every byte of the object has been written over by the constructor. As a straight memory check it looks OK, although if the class contains other objects which don't necessarily initialise themselves fully, you may be in trouble.
That said, my main question would be: Is it really an effective test? For example, is it critical that every attribute in the CSplitVector class is initialised by the initialisation list? Do you perhaps have some which may not need to be initialised at this point? Also, how about checking whether the attributes are set to values that you'd expect?
Instead of comparing byte by byte, you probably should use the right padding or word size, and test if any byte of each word got initialized. That way you will probably get around compiler using padding and constructor leaving uninitialized bytes between padded shorter-than-word fields.
To test the real padding size, shooting from the hip, following code should do it pretty reliably:
struct PaddingTest {
volatile char c; // volatile probably not needed, but will not hurt either
volatile int i;
static int getCharPadding() {
PaddingTest *t = new PaddingTest;
int diff = (int)(&(t->i)) - (int)&((t->c));
delete t;
return diff;
}
}
Edit: You still need the two objects, but you no longer compare them to each others, you just compare each initialized data to the memset value, and if either object has any change, it means the word got touched (also on the other one, it's just chance that it got initialized to same value you memset).
I found a solution for mentioned problems, tested it with initialized/not initialized pointers and with different length types.
In test header I added #pragma pack(1) (I am working on gcc)
#pragma pack(1)
#include <CSplitVector>
Test got a little bit complicated:
void CSplitVectorTest::TestConstructorInitialization()
{
const size_t memorySize = sizeof(CSplitVector);
char* pBuffer = (char*) malloc(memorySize);
memset(pBuffer,'?',memorySize);
CSplitVector* pSplitVector = new(pBuffer) CSplitVector;
// find pointers for all '?'
QList<char*> aFound;
char* pFoundChar = (char*) memchr(pBuffer,'?',memorySize);
while (pFoundChar)
{
aFound.append(pFoundChar);
char* pStartFrom = pFoundChar+1;
pFoundChar = (char*) memchr(pStartFrom,'?',memorySize-(int)(pStartFrom-pBuffer));
}
// if there are any '?'....
if (aFound.count())
{
// allocate the same area with '-'...
pSplitVector->~CSplitVector();
memset(pBuffer,'-',memorySize);
pSplitVector = new(pBuffer) CSplitVector;
// and check if places found before contain '-'
while (aFound.count())
{
pFoundChar = aFound.takeFirst();
if (*pFoundChar=='-')
{
// if yes then class has uninitialized attribute
TEST_FAILED("Constructor initialization list not complete!");
pSplitVector->~CSplitVector();
free(pBuffer);
return;
}
}
}
// if no then all attributes are initialized
pSplitVector->~CSplitVector();
free(pBuffer);
TEST(true);
}
Feel free to point any flaws in this solution.
I've been given a c api to work with and the minimum docs.
Developer is not around at the moment and his code is returning unexpected values (arrays not of expected length)
Im having problems with methods that return pointers to arrays and was wondering am I iterating over them correctly.
Q:does the following always return the correct len of an array?
int len=sizeof(sampleState)/sizeof(short);
int len=sizeof(samplePosition)/sizeof(int);
typedef unsigned char byte;
int len=sizeof(volume)/sizeof(byte);
And I iterate over the array using the pointer and pointer arithmetic (am I doing it correctly for all types below)
And last example below is multidimensional array? Whats the best way to iterate over this?
thanks
//property sampleState returns short[] as short*
short* sampleState = mixerState->sampleState;
if(sampleState != NULL){
int len=sizeof(sampleState)/sizeof(short);
printf("length of short* sampleState=%d\n", len);//OK
for(int j=0;j<len;j++) {
printf(" sampleState[%d]=%u\n",j, *(sampleState+j));
}
}else{
printf(" sampleState is NULL\n");
}
//same with int[] returned as int*
int* samplePosition = mixerState->samplePosition;
if(samplePosition != NULL){
int len=sizeof(samplePosition)/sizeof(int);
printf("length of int* samplePosition=%d\n", len);//OK
for(int j=0;j<len;j++) {
printf(" samplePosition[%d]=%d\n",j, *(samplePosition+j));
}
}else{
printf(" samplePosition is NULL\n");
}
Here byte is type def to
typedef unsigned char byte;
so I used %u
//--------------
byte* volume = mixerState->volume;
if(volume != NULL){
int len=sizeof(volume)/sizeof(byte);
printf("length of [byte* volume = mixerState->volume]=%d\n", len);//OK
for(int j=0;j<len;j++) {
printf(" volume[%d]=%u\n",j, *(volume+j));
}
}else{
printf(" volume is NULL\n");
}
Here is int[][] soundFXStatus.
do I just use same method above and have 2 loops?
//--------------
int** soundFXStatus = mixerState->soundFXStatus;
The sizeof(array)/sizeof(element) trick only works if you have an actual array, not a pointer. There's no way to know the size of an array if all you have is a pointer; you must pass an array length into a function.
Or better use a vector, which has a size function.
sizeof(sampleState)/sizeof(short);
This will only give the length of an array if sampleState is declared as an array, not a pointer:
short array[42];
sizeof(array)/sizeof(short); // GOOD: gives the size of the array
sizeof(array)/sizeof(array[0]); // BETTER: still correct if the type changes
short * pointer = whatever();
sizeof(pointer)/sizeof(short); // BAD: gives a useless value
Also, beware that a function argument is actually pointer even if it looks like an array:
void f(short pointer[]) // equivalent to "short * pointer"
{
sizeof(pointer)/sizeof(short); // BAD: gives a useless value
}
In your code, sampleState is a pointer; there is no way to determine the length of an array given only a pointer to it. Presumably the API provides some way to get the length (since otherwise it would be unusable), and you'll need to use that.
In C++, this is one reason why you would prefer std::vector or std::array to a manually allocated array; although that doesn't help you since, despite the question tags, you are using C here.
int len=sizeof(sampleState)/sizeof(short);
int len=sizeof(samplePosition)/sizeof(int);
sizeof is done at compile time, so this approach doesnt work if the length of the arrays are not known at compile time (for example the memory is reserved using a malloc).
ok ignore the method I used above it was all wrong - though you do need to know the length of the array which I finally got from the API developer.
Lately I've been diving into network programming, and I'm having some difficulty constructing a packet with a variable "data" property. Several prior questions have helped tremendously, but I'm still lacking some implementation details. I'm trying to avoid using variable sized arrays, and just use a vector. But I can't get it to be transmitted correctly, and I believe it's somewhere during serialization.
Now for some code.
Packet Header
class Packet {
public:
void* Serialize();
bool Deserialize(void *message);
unsigned int sender_id;
unsigned int sequence_number;
std::vector<char> data;
};
Packet ImpL
typedef struct {
unsigned int sender_id;
unsigned int sequence_number;
std::vector<char> data;
} Packet;
void* Packet::Serialize(int size) {
Packet* p = (Packet *) malloc(8 + 30);
p->sender_id = htonl(this->sender_id);
p->sequence_number = htonl(this->sequence_number);
p->data.assign(size,'&'); //just for testing purposes
}
bool Packet::Deserialize(void *message) {
Packet *s = (Packet*)message;
this->sender_id = ntohl(s->sender_id);
this->sequence_number = ntohl(s->sequence_number);
this->data = s->data;
}
During execution, I simply create a packet, assign it's members, and send/receive accordingly. The above methods are only responsible for serialization. Unfortunately, the data never gets transferred.
Couple of things to point out here. I'm guessing the malloc is wrong, but I'm not sure how else to compute it (i.e. what other value it would be). Other than that, I'm unsure of the proper way to use a vector in this fashion, and would love for someone to show me how (code examples please!) :)
Edit: I've awarded the question to the most comprehensive answer regarding the implementation with a vector data property. Appreciate all the responses!
This trick works with a C-style array at the end of the struct, but not with a C++ vector. There is no guarantee that the C++ vector class will (and it most likely won't) put its contained data in the "header object" that is present in the Packet struct. Instead, that object will contain a pointer to somewhere else, where the actual data is stored.
i think you might want to do like this:
`
struct PacketHeader
{
unsigned int senderId;
unsigned int sequenceNum;
};
class Packet
{
protected:
PacketHeader header;
std::vector<char> data;
public:
char* serialize(int& packetSize);
void deserialize(const char* data,int dataSize);
}
char* Packet::serialize(int& packetSize)
{
packetSize = this->data.size()+sizeof(PacketHeader);
char* packetData = new char[packetSize];
PacketHeader* packetHeader = (PacketHeader*)packetData;
packetHeader->senderId = htonl(this->header.senderId);
packetHeader->sequenceNum = htonl(this->header.sequenceNum);
char* packetBody = (packetData + sizeof(packetHeader));
for(size_t i=0 ; i<this->data.size() ; i++)
{
packetBody[i] = this->data.at(i);
}
return packetData;
}
void deserialize(const char* data,int dataSize)
{
PacketHeader* packetHeader = (PacketHeader*)data;
this->header.senderId = ntohl(packetHeader->senderId);
this->header.sequenceNum = ntohl(packetHeader->sequenceNum);
this->data.clear();
for(int i=sizeof(PacketHeader) ; i<dataSize ; i++)
{
this->data.push_back(data[i]);
}
}
`
those codes does not include bound checking and free allocated data, don't forget to delete the returned buffer from serialize() function, and also you can use memcpy instead of using loop to copy byte per byte into or from std::vector.
most compiler sometime add padding inside a structure, this would cause an issue if you send those data intact without disable the padding, you can do this by using #pragma pack(1) if you are using visual studio
disclaimer: i don't actually compile those codes, you might want to recheck it
I think the problem centres around you trying the 'serialise' the vector that way and you're probably assuming that the vector's state information gets transmitted. As you've found, that doesn't really work that way as you're trying to move an object across the network and things like pointers etc don't mean anything on the other machine.
I think the easiest way to handle this would be to change Packet to the following structure:
struct Packet {
unsigned int sender_id;
unsigned int sequence_number;
unsigned int vector_size;
char data[1];
};
The data[1] bit is an old C trick for variable length array - it has to be the last element in the struct as you're essentially writing past the size of the struct. You have to get the allocation for the data structure right for this, otherwise you'll be in a world of hurt.
Your serialisation function then looks something like this:
void* Packet::Serialize(std::vector<char> &data) {
Packet* p = (Packet *) malloc(sizeof(Packet) + data.size());
p->sender_id = htonl(this->sender_id);
p->sequence_number = htonl(this->sequence_number);
p->vector_size = htonl(data.size());
::memcpy(p->data, data[0], size);
}
As you can see, we'll transmit the data size and the contents of the vector, copied into a plain C array which transmits easily. You have to keep in mind that in your network sending routine, you have to calculate the size of the structure properly as you'll have to send sizeof(Packet) + sizeof(data), otherwise you'll get the vector cut off and are back into nice buffer overflow territory.
Disclaimer - I haven't tested the code above, it's just written from memory so you might have to fix the odd compilation error.
I think you need to work directly with byte arrays returned by the socket functions.
For these purposes it's good to have two distinct parts of a message in your protocol. The first part is a fixed-size "header". This will include the size of the byes that follow, the "payload", or, data in your example.
So, to borrow some of your snippets and expand on them, maybe you'll have something like this:
typedef struct {
unsigned int sender_id;
unsigned int sequence_number;
unsigned int data_length; // this is new
} PacketHeader;
So then when you get a buffer in, you'll treat it as a PacketHeader*, and check data_length to know how much bytes will appear in the byte vector that follows.
I would also add a few points...
Making these fields unsigned int is not wise. The standards for C and C++ don't specify how big int is, and you want something that will be predictable on all compilers. I suggest the C99 type uint32_t defined in <stdint.h>
Note that when you get bytes from the socket... It is in no way guaranteed to be the same size as what the other end wrote to send() or write(). You might get incomplete messages ("packets" in your terminology), or you might get multiple ones in a single read() or recv() call. It's your responsibility to buffer these if they are short of a single request, or loop through them if you get multiple requests in the same pass.
This cast is very dangerous as you have allocated some raw memory and then treated it as an initialized object of a non-POD class type. This is likely to cause a crash at some point.
Packet* p = (Packet *) malloc(8 + 30);
Looking at your code, I assume that you want to write out a sequence of bytes from the Packet object that the seralize function is called on. In this case you have no need of a second packet object. You can create a vector of bytes of the appropriate size and then copy the data across.
e.g.
void* Packet::Serialize(int size)
{
char* raw_data = new char[sizeof sender_id + sizeof sequence_number + data.size()];
char* p = raw_data;
unsigned int tmp;
tmp = htonl(sender_id);
std::memcpy(p, &tmp, sizeof tmp);
p += sizeof tmp;
tmp = htonl(sequence_number);
std::memcpy(p, &tmp, sizeof tmp);
p += sizeof tmp;
std::copy(data.begin(), data.end(), p);
return raw_data;
}
This may not be exactly what you intended as I'm not sure what the final object of your size parameter is and your interface is potentially unsafe as you return a pointer to raw data that I assume is supposed to be dynamically allocated. It is much safer to use an object that manages the lifetime of dynamically allocated memory then the caller doesn't have to guess whether and how to deallocate the memory.
Also the caller has no way of knowing how much memory was allocated. This may not matter for deallocation but presumably if this buffer is to be copied or streamed then this information is needed.
It may be better to return a std::vector<char> or to take one by reference, or even make the function a template and use an output iterator.