I have the following struct:
struct Datastore_T
{
Partition_Datastores_T cmtDatastores; // bytes 0 to 499
Partition_Datastores_T cdhDatastores; // bytes 500 to 999
Partition_Datastores_T gncDatastores; // bytes 1000 to 1499
Partition_Datastores_T inpDatastores; // bytes 1500 1999
Partition_Datastores_T outDatastores; // bytes 2000 to 2499
Partition_Datastores_T tmlDatastores; // bytes 2500 to 2999
Partition_Datastores_T sm_Datastores; // bytes 3000 to 3499
};
I want to set a char* to point to a struct of this type like so:
struct Datastore_T datastores;
// Elided: datastores is initialized with data here
char* DatastoreStartAddr = (char*)&datastores;
memset(DatastoreStartAddr, 0, 3500);
The problem I have is that DatastoreStartAddr always has a value of zero when it should point to the struct that has been initialized with data.
What am I doing wrong?
Edit: What I mean by zero is that the "values" in the structure are all zeros even after I initialize the structure. The address is not zero, it is the values in the struct that are zero.
Edit: I think I am asking the question wrong. Let's start over. If I have a struct that is initialized with data, and another object maintains a field member that is a pointer to that struct, if the struct is changed directly:
struct Datastore_T datastores;
char* DatastoreStartAddr = (char*)&datastores;
datastores.cmtDatastores.u16Region[0] = Scheduler.GetMinorFrameCount(); // byte 40,41
datastores.cmtDatastores.u16Region[1] = Scheduler.GetMajorFrameCount(); // byte 42,43
Shouldn't I be able to access these changes using the DatastoreStartAddr pointer?
EDIT: The following code tries to read the data set in datastores, but using the pointer to the struct:
CMT_UINT8_Tdef PayLoadBuffer[1500]= {NULL};
int TDIS = 0;
int DIS = 0;
int DSA = 0;
//copy DataStore info using address and size offsets
if ((PayLoadBuffer + TDIS + DIS) < IndvDEMMax)
{
memcpy((PayLoadBuffer + TDIS), Datastores+DSA, DIS);
TDIS += DIS;
}
In the memcpy((PayLoadBuffer + TDIS), Datastores+DSA, DIS) line, Datastores should point to structure and attempts to access an offset in that structure. But since the value is always zero, it copies zero in the PayLoadBuffer.
I don't know why you are getting an address of zero, but I would guess the code you don't show has something to do with it. Some other points:
Consider using an array of Partition_Datastores_T inside your struct
Do not use magic numbers for struct sizes, you want sizeof(Datastore_T )
There is no need for the intermediate char*
Edit: Bobby, to answer your supplementary question - yes you should be able to access it through a pointer, but not through a char * (without jumping through some hoops). You want:
struct Datastore_T datastores;
struct Datastore_T * DatastoreStartAddr = &datastores;
and when you use that pointer:
DatastoreStartAddr->cmtDatastores.u16Region[0] = Scheduler.GetMinorFrameCount();
Please note the use of the -> operator.
i just tested your code and it is not zero. Try to post bigger piece
You are doing it in the wrong order - should be like this
struct Datastore_T datastores;
char* DatastoreStartAddr = (char*)&datastores;
memset(DatastoreStartAddr, 0, sizeof(Datastore_T));
// Elided: datastores is initialized with data here
Now datastores is still initialized. And like everyone else says you might want this instead
struct Datastore_T * DatastoreStartAddr = datastores;
memset((void *)DatastoreStartAddr, 0, sizeof(Datastore_T));
I'm assuming that the code you are not showing is correct. It might be wise to show it to us for scrutiny. Likely, what I say below is not the problem at all.
Because of the cast, it might be that you're having aliasing issues here. If you have set aggressive compiler optimization flags (e.g. -fno-strict-aliasing on gcc), the compiler would assume that those two pointers can never refer to the same thing, because they have different types. Then either or both of the representations might be cached in different CPU registers, so updates to one would never be reflected in the other.
Again, this is a long shot. Considering the size of your struct (I didn't see that when I started answering your duplicate question), it is very unlikely that it would reside anywhere else but in main memory. But you could try turn down your compiler optimizations and see if it makes a difference.
At what point is your structure's values zero? If it's before the cast and memset(), the problem is with your initialization. If it is after the cast and memset(), then the values in your structure are zero because memset() overwrote with 0's the values you had initialized it with. The values in datastores should also be zero after the memset().
Related
I have a struct which looks like:
#pragma pack(1)
typedef struct WHEATHER_STRUCT {
uint8_t packetID; // Value 9
uint16_t packetSize; // Value 7
float cloudLayerAltitude; // Value 25000
} Wheather_Struct
This struct was initialized correctly. Due to design of an algorithm I need to read these three attributes values by a pointer offset. I thank about declare an array which have the size in bytes of these attributes. Just like:
int sizeOfStructAttributes = {1, 2, 4};
And finally to access these values do something like:
pointer = (*this->wheather_struct->packetID)
for (i=0; i<sizeof(sizeOfStructAttributes); i++)
cout << &pointer << ' ';
pointer = pointer + sizeOfStructAttributes[i];
Expected result:
9
7
25000
Could you help me please?
You have many problems with the code I will try to go through them all:
1- Your structure has padding values that depends on the architecture you are targeting maybe 3 or 7 bytes after the first member (packetID) it depends on the architecture and compiler.
2- You are initializing the pointer in a wrong way, it should be:
pointer = &(this->wheather_struct->packetID);
3- cout should be:
cout << *((datatype*)pointer) << ' ';
//datatype should be different in each loop iteration of course.
4- In case you are creating array of this strcutrue, I am not sure if you will face a problem of padding or not. It happens in very rare cases when you use different packing and padding due to mixing your code with other libraries that are compiled with different compiler directives or even uses #pragma to modify the behavior of the compiler during the compile time.
Finally I am sure there is no need at all to enumerate struct members with a pointer.
I encourage you to read about struct padding and packing, good place to start is this question on SO:
Structure padding and packing
One thing for sure, you won't be able to write these offsets manually. This is absolutely not a stable way of doing things, because your compiler might do optimizations such as aligning your struct members.
What you can do is this:
Wheather_Struct w;
long offsetsOfStructAttributes[3] = {0,
(char*)&w.packetSize - (char*)&w.packetID,
(char*)&w.cloudLayerAltitude - (char*)&w.packetID};
Notice that this is the byte difference in size.
Having told you how to do that, I have to say like people said in the comments, please find another way of doing this. This is not safe, unless you absolutely know what you're doing.
Your mistake is that you've assumed that the class has no padding between the members. But there must be padding in order to meet the alignment requirements of the members. Thus the offsets are not what you assume.
To get the offset of a class member, you can use the offsetof macro provided by the standard library. That said, without knowing what you need it for, I remain skeptical about it being appropriate. Note that offsetof works only if your class is a standard layout class. Otherwise the behaviour will be undefined. Your example WHEATHER_STRUCT is standard layout.
cout << &pointer << ' ';
Something like this can not possibly have the output that you expect. You take the address of the pointer, it cannot possibly give you the value of the pointed object that you wanted.
The way to get the pointed value is the indirection operator. But, indirection operator can only work correctly if the pointer is of correct type (float* for float members, uint16_t* for uint16_t members ...) but it cannot be of correct type since it has to be a pointer to a byte for the pointer arithmetic to work with the offsets.
Besides the offset, you also need to know the type of the variable in order to interpret the value. You could store the type in some structure. But you cannot cast the pointer to a type determined at runtime, so what you need is some runtime flow-structure such as a switch or a jump table for the conversion.
You'd better do not use pointer hack: one day underlying memory layout will be changed and your program may corrupt it.
Try to simulate metadata instead.
enum WheatherStructFields
{
wsfPacketID,
wsfPacketSize,
wsfCloudLayerAltitude,
wsfNone
};
typedef struct WHEATHER_STRUCT
{
uint8_t packetID;
uint16_t packetSize;
float cloudLayerAltitude;
void OutFieldValue(std::ostream& os, WheatherStructFields whatField)
{
switch (whatField)
{
case wsfPacketID:
os << (int)packetID;
break;
case wsfPacketSize:
os << packetSize;
break;
case wsfCloudLayerAltitude:
os << cloudLayerAltitude;
break;
default:
os << "Unsupported field: " << whatField;
}
}
} Wheather_Struct;
int main()
{
Wheather_Struct weather = { 9, 7, 25000 };
for (WheatherStructFields whatField = wsfPacketID; whatField < wsfNone;
whatField = (WheatherStructFields)((int)whatField + 1))
{
weather.OutFieldValue(std::cout, whatField);
std::cout << " ";
}
}
There are two problems with your approach:
Firstly, it requires you to get the sizes right. Use sizeof to do that. So your array would look like:
size_t sizeOfStructAttributes = {sizeof(wheather_struct::packet_id),
sizeof(wheather_struct::packet_size),
sizeof(wheather_struct::cloudLayerAltitude) };
The second (more serious) problem is that you don't allow for padding in your structure. Almost all compilers will (unless specially instructed), insert a padding byte between packet_id and packet_size so that everything is nicely aligned. Fortunately, there is a solution for that too - use the offsetof macro (defined in stddef.h):
size_t offsetOfStructAttributes = {offsetof(wheather_struct, packet_id),
offsetof(wheather_struct, packet_size),
offsetof(wheather_struct, cloudLayerAltitude) };
The code then becomes:
for (size_t offset: offsetsOfStructAttributes) {
pointer = &(this->wheather_struct->packetID) + offset
cout << pointer << ' ';
}
Actually: the above code fixes a third problem with your code: sizeof() returns the size in bytes, which is unlikely to be the element count.
Finally, your variables have a typo: meteorology is concerned with whether the weather will be fine or not. You have confused the two words and I am pretty sure you mean "weather".
I have assignment which asks one to write a function for any data type.The function is supposed to print the bytes of the structure and identify the total number of bytes the data structure uses along with differentiating between bytes used for members and bytes used for padding.
My immediate reaction, along with most of the classes reaction was to use templates. This allows you to write the function once and gather the run time type of the objects passed into the function. Using memset and typeid's one can easily accomplish what has been asked. However, our prof. just saw our discussion about templates and damned templates to hell.
After seeing this I was thrown for a loop and I'm looking for a little guidance as the best way to get around this. Some things I've looked into:
void pointers with explicit casting (this seems like it'd get messy)
base class with virtual functions only from which all data structures inherit from, seems a bit odd to do.
a base class with 'friendships' to each of our data structures.
rewriting a function for each data structure in our problem set (what I imagine is the worst possible solution).
Was hoping I overlooked a common c++ tool, does anyone have any ideas?
Treat the function as stupid as possible, in fact, treat it as if it doesn't know anything and all information must be passed to it.
Parameters to the function:
Structure address, as a uint8_t *. (Needed to print the bytes)
Structure size, in bytes. (Needed to print the bytes and to print the
total size)
A vector of member information: member length OR the sum of the bytes used by the members.
The vector is needed to fulfill the requirement of printing the bytes used by the members and the bytes used by padding. Optionally you could pass the sum of the members.
Example:
void Analyze_Structure(uint8_t const * p_structure,
size_t size_of_structure,
size_t size_occupied_by_members);
The trick of this assignment is to figure out how to have the calling function determine these items.
Hope this helps.
Edit 1:
struct Apple
{
char a;
int weight;
double protein_per_gram;
};
int main(void)
{
Apple granny_smith;
Analyze_Structure((uint8_t *) &granny_smith,
sizeof(Apple),
sizeof(granny_smith.a)
+ sizeof(granny_smith.weight)
+ sizeof(granny_smith.protein_per_gram);
return 0;
}
I have assignment which asks one to write a function for any data type.
This means either templates (which your prof. dismissed), void*, or variable number of arguments (simiar to printf).
The function is supposed to print the bytes of the structure
void your_function(void* data, std::size_t size)
{
std::uint8_t* bytes = reinterpret_cast<std::uint8_t*>(data);
for(auto x = bytes; x != bytes + size; ++x)
std::clog << "0x" << std::hex << static_cast<std::uint32_t>(*x) << " ";
}
[...] and identify the total number of bytes the data structure uses along with differentiating between bytes used for members and bytes used for padding.
On this one, I'm lost: the bytes used for padding are (by definition) not part of the structure. Consider:
struct x { char c; char d; char e; }; // sizeof(x) == 3;
x instance{ 0, 0, 0 };
your_function(&instance, sizeof(x)); // passes 3, not 4 (4 for 32bits architecture)
Theoretically, you could also pass alignof(instance) to the function, but that won't tell you the alignment of the fields in memory (as far as I know it is not standardized, but I may be wrong).
There are a few possibilities here:
Your prof. learned "hacky" C++ that was considered good code 10 or 20 years ago and didn't update his knowledge (C-style code, pointers, direct memory access and "smart hacks" are all in here).
He didn't know how to express exactly what he wanted or the terminology to use ("write a function for any data type" is too vague: as a developer, if I got this assignment, the first thing to do would be to ask for details - like "how will it be used?" and "what is the expected function signature").
For example, this could be achieved - to a degree - with macros, but if he wants you to use macros in place of functions and templates, you should probably contemplate changing professors.
He meant that you should write some arbitrary data type (like my struct x above) and define your API around that (unlikely).
I am not sure that such a function can be built without a minimum of introspection: you need to know what the struct members are, otherwise you only have access to the size of the struct.
Anyway, here is my proposal for a solution that should work without introspection, provided the user of the code "cooperates".
Your functions will take as arguments void* and size_t for the address and sizeof of the struct.
0) let the user create a struct of the desired type.
1) let the user call a function of yours that sets all bytes to 0.
2) let the user assign a value to every field of the struct.
3) let the user call a function of yours that keeps a record of every byte that is still 0.
4) let the user call a function of yours that sets all bytes to 1.
5) let the user assign a value to every field of the struct again. (Same values as the first time!)
6) let the user call a function of yours and count the bytes that are still 1 AND were marked before. These are padding bytes.
The reason to try with values 0 then 1 is that the values assigned by the user could include bytes 0; but they can't be bytes 0 and bytes 1 at the same time so one of the test will exclude them.
struct _S { int I; char C } S;
Fill0(S, sizeof(S));
// User cooperation
S.I= 0;
S.C= '\0';
Mark0(S, sizeof(S)); // Has some form of static storage
Fill1(S, sizeof(S));
// User cooperation
S.I= 0;
S.C= '\0';
DetectPadding(S, sizeof(S));
You can pack all of this in a single function that takes a callback function argument that does the member assignments.
void Assign(void* pS) // User-written callback
{
struct _S& S= *(struct _S)pS;
S.I= 0;
S.C= '\0';
}
What's the usefulness of the function memset()?.
Definition: Sets the first num bytes of the block of memory pointed by ptr to the
specified value (interpreted as an unsigned char).
Does this mean it hard codes a value in a memory address?
memset(&serv_addr,0,sizeof(serv_addr) is the example that I'm trying to understand.
Can someone please explain in a VERY simplified way?
memset() is a very fast version of a relatively simple operation:
void* memset(void* b, int c, size_t len) {
char* p = (char*)b;
for (size_t i = 0; i != len; ++i) {
p[i] = c;
}
return b;
}
That is, memset(b, c, l) set the l bytes starting at address b to the value c. It just does it much faster than in the above implementation.
memset() is usually used to initialise values. For example consider the following struct:
struct Size {
int width;
int height;
}
If you create one of these on the stack like so:
struct Size someSize;
Then the values in that struct are going to be undefined. They might be zero, they might be whatever values happened to be there from when that portion of the stack was last used. So usually you would follow that line with:
memset(&someSize, 0, sizeof(someSize));
Of course it can be used for other scenarios, this is just one of them. Just think of it as a way to simply set a portion of memory to a certain value.
memset is a common way to set a memory region to 0 regardless of the data type. One can say that memset doesn't care about the data type and just sets all bytes to zero.
IMHO in C++ one should avoid doing memset when possible since it circumvents the type safety that C++ provides, instead one should use constructor or initialization as means of initializing. memset done on a class instance may also destroy something unintentionally:
e.g.
class A
{
public:
shared_ptr<char*> _p;
};
a memset on an instance of the above would not do a reference counter decrement properly.
I guess that serv_addr is some local or global variable of some struct type -perhaps struct sockaddr- (or maybe a class).
&serv_addr is taking the address of that variable. It is a valid address, given as first argument to memset. The second argument to memset is the byte to be used for filling (zero byte). The last argument to memset is the size, in bytes, of that memory zone to fill, which is the size of that serv_addr variable in your example.
So this call to memset clears a global or local variable serv_addr containing some struct.
In practice, the GCC compiler, when it is optimizing, will generate clever code for that, usually unrolling and inlining it (actually, it is often a builtin, so GCC can generate very clever code for it).
It is nothing but setting the memory to particular value.
Here is example code.
Memset(const *p,unit8_t V,unit8_t L) , Here the P is the pointer to target memory, V is the value to the target buffer which will be set to a value V and l is the length of the data.
while(L --> 0)
{
*p++ = V;
}
memset- set bytes in memory
Synopsis-
#include<string.h>
void *memset(void *s,int c,size_t n)
Description- The memset() function shall copy c (converted to an unsigned char) into each of the first n bytes of the object pointed to by s.
Here for the above function , the memset() shall return s value.
I need to use a function (part of an API) which stores some requested data into a dynamic sized struct using call by reference. The struct is defined as follows - it concerns access control lists of either posix or NFS4 version, but that is just the use case, I guess.
typedef struct my_struct
{
unsigned int len; /* total length of the struct in bytes */
... /* some other static sized fields */
unsigned int version; /* 2 different versions are possible */
unsigned int amount; /* number of entries that follow */
union {
entry_v1_t entry_v1[1];
entry_v2_t entry_v2[1];
};
} my_struct_t;
There are 2 versions of the entries and I know which one I will obtain (v1). Both entry_v1_t and entry_v2_t are fixed (but different) sized structs just containing integers (so I guess they are not worth being explained here). Now I need to use an existing function to fill my structure with the information I need using Call by Reference, the signature is as follows, including the comments - I don't have access to the implementation:
int get_information(char *pathname, void *ptr);
/* The ptr parameter must point to a buffer mapped by the my_struct
* structure. The first four bytes of the buffer must contain its total size.
*/
So the point is, that I must allocate memory for that struct but don't know for how much entries (and, as consequence, the total size) I must allocate. Have you ever dealt with such a situation?
Under Windows API there are many such functions, you normally call them with some NULL pointer to get size of the buffer, then call again with allocated buffer. In case during next call size of buffer have changed function returns error and you need allocate again. So you do it in a while loop till function returns with success.
So your get_information must implement somehow such mechanisms, either it returns false if buffer is to small or returns its correct size if ptr is NULL. But that is just my guess.
OK I thing I figured out how it works. Thanks for your ideas and notes. I declared a my_struct pointer and allocated minimum space for the fixed sized fields (5) before the dynamic array => 5 * sizeof(unsigned int). Invoking get_information with that pointer returns -1 and sets errno = 28 and strerror(errno) = "No space left on device".
But, it sets the my_struct->len field to the required size and that seems to be the answer to my question - how should you know? No I can invoke get_information initially with the minimum space and figure out how much I need to allocate, and afterwards call it again with the right sized memory allocated to get the information successfully.
The loop solution seems to make sense anyway and would have been my next try - since there are usually just a few entries in that dynamic array.
Thank you.
I need to craft a packet that has a header, a trailer, and a variable length payload field. So far I have been using a vector for the payload so my struct is set up like this:
struct a_struct{
hdr a_hdr;
vector<unsigned int> a_vector;
tr a_tr;
};
When I try to access members of the vector I get a seg fault and a sizeof of an entire structs give me 32 (after I've added about 100 elements to the vector.
Is this a good approach? What is better?
I found this post
Variable Sized Struct C++
He was using a char array, and I'm using a vector though.
Even though the vector type is inlined in the struct, the only member that is in the vector is likely a pointer. Adding members to the vector won't increase the size of the vector type itself but the memory that it points to. That's why you won't ever see the size of the struct increase in memory and hence you get a seg fault.
Usually when people want to make a variable sized struct, they do so by adding an array as the last member of the struct and setting it's length to 1. They then will allocate extra memory for the structure that is actually required by sizeof() in order to "expand" the structure. This is almost always accompanied by an extra member in the struct detailing the size of the expanded array.
The reason for using 1 is thoroughly documented on Raymond's blog
http://blogs.msdn.com/oldnewthing/archive/2004/08/26/220873.aspx
The solution in the other SO answer is c-specific, and relies on the peculiarities of c arrays - and even in c, sizeof() won't help you find the "true" size of a variable size struct. Essentially, it's cheating, and it's a kind of cheating that isn't necessary in C++.
What you are doing is fine. To avoid seg faults, access the vector as you would any other vector in C++:
a_struct a;
for(int i = 0; i < 100; ++i) a.a_vector.push_back(i);
cout << a.a_vector[22] << endl; // Prints 22
i saw this implementation in boost..it looks really neat...to have a variable
length payload....
class msg_hdr_t
{
public:
std::size_t len; // Message length
unsigned int priority;// Message priority
//!Returns the data buffer associated with this this message
void * data(){ return this+1; } //
};
this may be totally un-related to the question, but i wanted to share the info