let's say i got a struct like this:
typedef struct myInfo {
WORD myCount;
WORD data[0];
} myInfo;
Well, i would like to use this struct (which is declare extern by the way), in another .c source file, where i've got a function like this:
void dynamic_init(struct myInfo dummy){
macroPut(5, dummy.myCount, &dummy.mydata); <- doesn't work
macroPut(5, dummy.myCount, &externalInitialized.mydata); <- works
}
This way i would dynamically use this dynamic_init without worring about the struct name...
But as u could easily see in my snippet above, it works only with the inizialized struct...but if i call the function this way:
dynamic_init(externalInitialized);
It won't work.
In other words i've got to do something like this:
dynamic_init( externalInitialized.myCount, externalInitialized.mydata);
And i have the result expected.
The main mistery is that is the "mydata" WORD that corrupt everything.
the "myCount" works as expected if i do this way:
dynamic_init( externalInitialized, externalInitialized.mydata);
and then:
void dynamic_init(struct externalInitialized dummy, WORD *dynData){
macroPut( 5, dummy.myCount, &dynData); <- works
}
I know it's dumb, but it's just to show the exact wrong part.
Thanks!
When you pass structure to function, compiler generates code to copy structure contents, so function gets its own copy of parameters that it can freely modify without affecting original. Copying is performed for sizeof struct bytes.
Your main problem here is that your structure have flexible array member, so its sizeof have very little to do with real size it will occupy.
E.g. structure's in question sizeof is 4 (last field is array of 0 elements so it doesn't increas sizeof), but when you allocating memory for structure, you actually allocating much more - and saving 'real' size in structure field. That way, accessing data array will actually get elements outside of structure itself (placed right next bytes to it); however, compiler don't know that (and cannot know, as size differs from one structure instance to another). For the same reason you cannot directly place that structure on stack and safely fill data - because that will touch bytes that doesn't belong to it and corrupt other things (technically it can be placed on stack, but you have to manually align it within on-stack array of enough size).
Flexible array member have other limitations, like you cannot make an array of that type of structures (once again - technically you can, but it makes no sense since array indexing relies on sizeof).
So, short answer is "don't pass flexible-sized structures by value". Or even think twice before passing structure by value at all - copying isn't free, after all.
Related
Given a large struct pointer, say, large_ptr, and I want to assign it to a global var of the same type, let's call it g_large, then I have 2 options:
The first one using memcpy:
memcpy(&g_large, large_ptr, sizeof(g_large));
The second one using assignment:
g_large = *large_ptr;
Due to lack of memory and stack size in an embedded software I would like to know, does the second way behave like memcpy, or does it create a tmp var to do the assignment? Is there any standard for this?
If it behaves like memcpy then I'd prefer it for being shorter. But if it creates a temporary var, it might be a problem for the stack.
Your experience & knowledge will be appreciated!
Edit
A few mentioned I need to compile and view the assembly.
This is a process I need to learn, since it's a cross compiler, which generates asm files that are binary and need to be parsed. Not a simple task. I could do that, but it will take time.
I may misunderstood but in ur memcpy function the sizeof(g_large) will always return 8 bytes as result since the size of a pointer in c is 8 bytes. Therefore you get the pointer size and not the struct size. It's like you can not find the size of an array if you only have the pointer addressing it.
[edit: oh yeah i misunderstood but anyway the following section is still recommended]
What I would do:
dinamically allocate memory in main function
pass the allocated memory pointer to the local function where you want to work with your struct
extend the allocated memory if needed while working with your struct on the designated memory space
at the end of the local function you will already have ur struct stored in main function memory space without any copy function needed
Hello i am trying to learn and build data structures in c and i want to store integers progressively in the stack.
my struct is like this:
typedef struct STACK_NODE_s *STACK_NODE;
typedef struct STACK_NODE_s{
STACK_NODE forward;
void *storage;
} STACK_NODE_t;
typedef struct L_STACK_s{
STACK_NODE top;
} L_STACK_t, *L_STACK;
In a while loop i want to read and store my chars in integer form.
//assume that str is an proper string
//assume that we have a linked stack called LS
int i=0;
int temp;
while(str[i]!='\0'){
tmp=str[i]-'0';
push(LS,(void *)&tmp);
}
I know this won't work properly as we store the same variable's adress over and over again.
Do i need to allocate an auxiliary array in order to store them 1 by 1 or is there a better way to do this?
The answer must address two separate aspects of your question:
How to organize some collection of items, and where to get the memory from to do that.
First code snippet / Linked list format
The first code snippet is good the way it is.
It sets up a linked list, which has its pros and cons, but serves very well if you don't know the number of items in advance, if you want to be able to quickly remove or insert items somewhere in the middle of the list, and if you don't mind that looking up one certain entry inside the list costs you O(N) effort.
For a generic library-like implementation...
... void* is as good as it goes with ANSI C.
In C++, for example, you could make a template that leaves open the type that is stored in the list (or better yet, you would directly reuse the well-known STL implementation in class forward_list<int>).
Sadly, ANSI C doesn't have something comparable.
One solution is the one you picked, create int objects and hook their addresses into your list of void*.
Another solution for a generic library implementation is to use a precompiler macro for the type, and to define this macro above a header file that holds the generic implementation. This tries to resemble the clean C++ solution, but with precompiler it is not typesafe, so this approach is far from beautiful and comes with several risks.
Second code snippet / Memory allocation
Creating the list with void* instead of int (or whatever non-pointer type) requires you to allocate further memory beside the list.
I. e., it is not only that you have to allocate every list item (= variable of type STACK_NODE_t) but also the actual entry value (e. g., *(int*)(LS->storage)).
This means you have to allocate/deallocate the data in some other way that outlives the stack.
On most systems, you can use malloc/free for that, and you only have to take into account the size of the heap available for malloc and the time de-/allocating takes.
If the list shall implement real-time requirements or on embedded systems, you may not have malloc or you may not be allowed to use it.
Then you have to allocate and implement your own heap (= memory pool of storage items) for your list.
How to implement such a memory pool with desired properties is a separate question that would take us to far here.
In any case, you must not use the pointer to a stack variable (like a local variable inside a function) because the memory "behind" that variable will not be reserved for this purpose once the function exits, and the memory may be used for something different in the meantime.
This is, however, what the second code snippet does apparently.
As you noticed yourself, taking this path...
we store the same variable's adress over and over again.
Reusing the memory position for another entry of the same list is an extreme case of the risk explained above.
I solved the problem using an auxiliary array like i anticipated. If someone comes up with a better solution its more than welcome.
In the file include/linux/ieee80211.h we have:
struct ieee80211_mgmt {
...
union {
...
struct {
__le16 capab_info;
__le16 listen_interval;
/* followed by SSID and Supported rates */
u8 variable[0];
} __packed assoc_req;
...
} u;
} __packed __aligned(2);
I need to modify some fields in this struct. For instance, to modify capab_info I would do it by:
...
struct ieee80211_mgmt *mgmt_hdr = skb->data;
mgmt_hdr->u.assoc_req.capab_info = 0xABCD;
But if I want to modify/insert the "SSID" field that would be localized somewhere in variable array, I do not know where and how I should allocate and modify it.
The above code I supposing skb->data struct was already allocated by mac80211 module, and what I want to do it just insert a new field (which is not listed in the static struct).
I did not find any similar code over kernel tree to use as an example. I appreciate any points you can provide me to understand it better. Thank you very much!
Permitting a structure to have a length-zero array as its final member is a GCC extension with substantially the same semantics as a standard flexible array member. The member is accessible by name and according to the element type of the array, like any other, and you may access as many elements as the actual allocated size of the structure permits. For example, mgmt_hdr->u.assoc_req.variable[i] for i within the allowed range.
Of course, to know how much data you can access you need either to rely on a stored length somewhere or to rely on some characteristic of the data itself, such as a terminator / sentinel. If you're hoping to extend the array in-place then you may be out of luck, and if you don't know how much space was allocated then you certainly are. In such cases, your only viable alternative is to reallocate the whole object larger, and replace all pointers to the original one with pointers to the new one. If you can't be sure of doing that, then extending the array is not an option for you, but you can still modify the existing content if you can tell where it ends.
Ran into a design problem when using memcpy and building a generic HashTable in c. The HashTable maps unsigned int keys to void * data that I memcpy over.
// Random example
void foo() {
// Suppose `a` is a struct that contains LinkedLists, char arrays, etc
// within it.
struct *a = malloc(sizeof(a));
HashTable ht = ht_create(sizeof(a));
// Insert the (key, value) pair (0, a) into the hash table ht
ht_insert(ht, 0, a);
// Prevent memory leak
destroy_struct(a);
// Do stuff...
// ... eventually destroy ht
ht_destroy(ht);
}
Now, given struct a has LinkedLists and pointers within it, and the HashTable is using memcpy, my understanding is that it copies over shallow copies of these pointers. Thus, ht_insert mallocs space for a new entry, shallowly copies over data from a, and inserts the new entry into its table.
Consequently, unless I free struct a completely with some function destroy_struct, I am leaking memory. However, given I'm shallowly copying data in ht_insert, when I call destroy_struct(a), I will have accidentally freed the data pointed to within the hash table's entry as well!
Is the logic above correct, and if so, should I use a some recursive memcpy function that makes sure to deep copy all data from struct a to the HashTable?
Firstly, if your code doesn't reproduce the problem you are explaining, you shouldn't include it. The problem your code produces is compiler errors. This doesn't help your question, does it?
Now, given struct a has LinkedLists and pointers within it, and the HashTable is using memcpy, my understanding is that it copies over shallow copies of these pointers.
If you are simply copying the internal representation of a struct whatever * into the internal representation of a void *, then you are asking for trouble. There is no guarantee that the two representations are identical. It's possible that one pointer type might be larger than the other, that they use different endianness (if they're implemented as typical quasi-integers) or other internal differences might exist. You should convert one pointer to the other type, and then you could simply assign it... In fact, because one of the types is void * that conversion will happen implicitly when you assign.
Consequently, unless I free struct a completely with some function destroy_struct, I am leaking memory.
From what you have described, you should only call free on that pointer value once (and only once) you are done with it, and your program no longer has any use for it (e.g. after you have removed it from the hashtable). This goes for all non-null pointers that are returned by malloc, realloc or calloc. To clarify: if x and y store the same pointer returned by one of those functions, free should only be called ONCE on ONE OF THEM because they contain the same value.
Is the logic above correct, and if so, should I use a some recursive memcpy function that makes sure to deep copy all data from struct a to the HashTable?
I highly recommend breaking this question up into two or more separate questions, because it's double-barreled. I could simply answer "yes" (or "no"). Would that give you any meaningful information?
This brings me back to what I first wrote. I can only guide you based on what you've written here, which might not be reflective of the code that you use (especially given the influences of the erroneous code you've given). In order to guide you better, I would need to see all of the gaps filled in. I would need to see a testcase that creates a hashtable, inserts into the hashtable, uses the hashtable, removes from the hashtable and cleans up the hashtable to determine whether or not your operations are leaking anywhere... but most importantly, this testcase would need to be COMPILABLE! Otherwise it can't do any of those things, because it can't compile.
A struct with a flexible array member, apparently, is not intended to be declared, but rather used in conjunction with a pointer to that struct. When declaring a flexible array member, there must be at least one other member, and the flexible array member must be the last member in that struct.
Let's say I have one that looks like this:
struct example{
int n;
int flm[];
}
Then to use it, I'll have to declare a pointer and use malloc to reserve memory for the structure's contents.
struct example *ptr = malloc(sizeof(struct example) + 5*sizeof(int));
That is, if I want my flm[] array to hold five integers. Then, I can just use my struct
like this:
ptr->flm[0] = 1;
My question is, shouldn't I be able to just use a pointer instead of this? Not only would it be compatible pre-C99, but I could use it with or without a pointer to that struct.
Considering I already have to use malloc with the flm, shouldn't I just be able to do this?
Consider this new definition of the example struct;
struct example{
int n;
int *notflm;
}
struct example test = {4, malloc(sizeof(int) * 5)};
I'd even be able to use the replacement the same way as the flexible array member:
Would this also work? (Provided the above definition of example with notflm)
struct example test;
test.n = 4;
notflm = malloc(sizeof(int) * 5);
Pointers are not arrays. The basic reasons for choosing which to use are the same as they always are with arrays versus pointers. In the special case of flexible array members, here are some reasons you may prefer them over a pointer:
Reducing storage requirements. A pointer will enlarge your structure by (typically) 4 or 8 bytes, and you'll spend much more in overhead if you allocate the pointed-to storage separately rather than with a single call to malloc.
Improving access efficiency. A flexible array member is located at a constant offset from the structure base. A pointer requires a separate dereference. This affects both number of instructions required to access it, and register pressure.
Atomicity of allocation success/failure. If you allocate the structure and allocate storage for it to point to as two separate steps, your code for cleaning up in the failure cases will be much uglier, since you have the case where one succeeded and the other failed. This can be avoided with some pointer arithmetic to carve both out of the same malloc request, but it's easy to get the logic wrong and invoke UB due to alignment issues.
Avoiding need for deep-copy. If you use a flexible array instead of a pointer, you can simply memcpy (not assign, since assignment can't know the flexible array length) to copy the structure rather than having to copy the pointed-to data too and fix up the pointer in the new copy.
Avoiding need for deep-free. It's very convenient and clean to be able to just free a single object rather than having to free pointed-to data too. This can also be achieved with the "carving up a single malloc" approach mentioned above, of course, but flexible arrays make it easier and less error-prone.
Surely many more reasons...
Those concepts are definitely not necessary as you have pointed out yourself.
The differences between the two that you have demonstrated are where your data is located in memory.
In the first example with flexible array your metadata and the array itself are in the same block of memory and can be moved as one block (pointer) if you have to.
In the second example your metadata is on the stack and your array is elsewhere on the heap. In order to move/copy it you will now need to move two blocks of memory and update the pointer in your metadata structure.
Generally flexible size arrays are used when you need to place an array and it's metadata spatially together in memory.
An example where this is definitely useful is for instance when placing an array with it's metadata in a file - you have only one continuous block of memory and each time you load it it will (most likely) be placed in a different location of your VM.