Allocate space for struct pointer member through constructor - c

I want to use structs like objects in C.
Suppose I have the following:
typedef struct {
/* ... */
size_t *pages_len;
} book;
And I use the following method to construct it:
int book_init(/* some args... */, book * b) {
/* do some validation */
/* compute the number of pages n_pages */
b->pages_len = (size_t*) calloc(n_pages, sizeof(size_t));
/* compute pages_len based on some args */
return 0;
}
Then I construct an object like this:
book *my_book = (book*)malloc(sizeof(my_book));
if (book_init(/* some args */, my_book) == 0) {
/* do something */
}
And I destroy my object like: book_destroy(book *b) where I free(b->pages_len).
Is this correct or am I missing something? I can't show the original code but I am having trouble:
Accessing b->pages_len after the init method.
Destroying the object. I am having memory corruption.
As requested, a minimal reproducible example:
/* book.h */
#ifndef BOOK_HEADER_
#define BOOK_HEADER_
#include <ctype.h>
typedef struct
{
size_t pages_count;
size_t *pages_len;
} * book;
int book_create (book b);
#endif /* BOOK_HEADER_ */
/* book.c */
#include "book"
int
book_create (book b)
{
b->pages_len = calloc (3, sizeof (b->pages_len));
b->pages_len[2] = 20;
return 0;
}
/* test.c */
#include "book.h"
int main(int argc, char** argv) {
book my_book = (book)malloc (sizeof (book));
int r = book_create (my_book);
printf ("\n%lu\n", my_book->pages_len[2]);
free (my_book->pages_len);
free (my_book);
}
What I get from my memory leak detector is that free(my_book) gives a Memory corruption (written out of bounds?) error. One thing that fixed this error was changing the order of pages_count and pages_len but I don't know why.
I just typed the above example, so if there is any typo or syntactic error, please let me know. Thank you.

book my_book = malloc(sizeof(book)) is wrong. Note that the type of book is pointer to your struct, but you want to allocate enough space for the struct itself. So as the code stands, you will need to write malloc(sizeof(*my_book)).
However, using typedef to define a name for a pointer is usually bad style; it leads to confusion, and you will find it very awkward that your struct type doesn't have a name. A better way to write this would just be as
struct book
{
size_t pages_count;
size_t *pages_len;
};
struct book *my_book = malloc(sizeof(*my_book));
In this case malloc(sizeof(struct book)) would also work, but will become broken if you ever change the type of my_book.
It's often suggested that you not typedef away the struct, and just keep calling it struct book everywhere, because it's usually good to remember what kind of object you are working with. But if you must, you can still do typedef struct book book; afterwards. As mentioned, I would not recommend typedef struct book *book;.
Casting the result of malloc should never be necessary in C. You presumably included it because you got a warning about the return type of malloc, but the correct fix is to include the standard header <stdlib.h>. Indeed, this is precisely the reason why people usually recommend that you do not cast the result of malloc, because it can silence warnings that indicate a real bug. See Do I cast the result of malloc? for much more on this topic.
You also need <stdio.h> in test.c.
Also, create_book should return a value (but this is not the cause of your crash, since you never use it).
It is not surprising that rearranging the struct members made the bug appear to go away. What probably happened is something like this. On a typical 64-bit system, size_t and pointers are each 8 bytes. So you had allocated 8 bytes for your struct, when its size is actually 16. But you only actually wrote to the pages_len member. So if pages_len is the first member of the struct, and you never write to the pages_count member, you are only writing within the 8 bytes you allocated, and nothing goes wrong. Of course, the code was still broken, and as soon as you added any code that used the pages_count member, or added or rearranged any members of your struct, the bug would be back.
But in general, blindly changing things until a bug goes away is an extremely bad idea when programming in C. You may very easily do something that only masks the bug and makes it harder to find. There's no substitute for actually understanding what is happening.

Related

Is it possible to allocate structs on the stack with its definition hidden in a source file?

I have the following header file:
struct StackList_s;
typedef struct StackList_s StackList_t;
// From here I add in the method signatures
And the following source file:
struct StackList_s
{
integer_t count;
struct StackListNode_s *top; // Here begins the linked list
// Some other members that store information about the stack
integer_t version_id;
};
// From here I define StackListNode_s and implement the StackList_s functions
// Note that the user will never manipulate directly a StackListNode_s
// There are functions that will handle the free() of each node correctly
I hide the struct definition in the source file so that anyone using this stack can't modify directly its members, since changing them requires some input treatment or checking for certain invalid states.
Currently, to get a new stack you have to use the following:
// malloc(sizeof(StackList_t)) and set members to default
StackList_t *stack = stl_new(/* Some info parameters */);
But I can only do this allocating a StackList_t in the heap. What I want to do is to have the StackList_t allocated on the stack and then its nodes can be allocated in the heap allong with their data and pointers to other nodes. This way I can give the user a choice, if either the struct is being used locally or if he will pass it around functions as an allocated resource.
StackList_t stack;
stl_init(&stack, /* Info parameters */); // No malloc, only setting members to 0
But of course I can't do this because the definition of struct StackList_s is in the source file. So here are my questions:
Is it possible to, at the same time, not allow access to members of a struct and allocate that same struct in the stack?
Is there any way to tell the compiler the size of my struct?
You can do that with VLAs or alloca in Linux:
Library header:
struct StackList_s;
typedef struct StackList_s StackList_t;
extern const size_t StackList_size;
// If you're using VLAs
extern const size_t StackList_align;
StackList_t* stl_init_inline(char stack_source[], ...);
Library source:
#include "header.h"
struct StackList_s {
// ...
};
const size_t StackList_size = sizeof(StackList_t);
// If you're using VLAs
#include <stdalign.h>
#include <stdint.h>
const size_t StackList_align = alignof(StackList_t);
StackList_t* stl_init_inline(char stack_source[], ...) {
// align the address to the nearest multiple of StackList_align
uintptr_t address = (uintptr_t) ((void*) stack_source);
if (address % StackList_align != 0) {
address += StackList_align - address % StackList_align;
}
StackList_t* stack = (StackList_t*) ((void*) address);
stl_init(stack, ...);
return stack;
}
Main source
#include <header.h>
StackList_t* stack = alloca(Stacklist_size);
stl_init(stack, ...);
char stack_source[StackList_size + StackList_align - 1]; // Not compile time.
StackList_t* stack = stl_init_inline(stack_source, ...);
This would allocate it on the stack, and you won't need to free it, but it's slower and more verbose than just StackList_t stack_source;. (And alloca is Linux only)
For the second question, you need the full definition of a struct to get it's size. Common pitfalls include the fact that sizeof(struct { int a; }) == sizeof(struct { int a; }) can be false. It probably won't be though, so you can do #define StackList_size sizeof(struct { integer_t count; struct StackListNode_s *top; integer_t version_id; }) but that also leads to a lot of code duplication.
I personally would just put the struct definition in the header file, and just declare "don't mess with the members or my methods won't work" in a comment somewhere (Maybe making the names start with _ to give a hint that they are private)
You could do something similar to Artyer's answer without using VLA's by using a #define instead
Header:
#define STACKLISTSIZE 32
typedef uint8_t stl_storage[STACKLISTSIZE];
typedef struct stacklist_s stacklist_t;
stacklist_t* stl_create_from_stack(stl_storage b); //user provides memory
stacklist_t* stl_allocate(void); //library allocates memory, user must free.
Source:
int myfunction()
{
stl_storage x;
stacklist_t* sp = stl_create_from_stack(x);
//do something with sp.
}
Make sure you have a compile-time assert that sizeof(stack_s) == STACKSTRUCTSIZE in the implementation file.
Some implementations guarantee that calls between compilation units will be processed in a fashion consistent with the platform's Application Binary Interface (ABI), without regard for what a called function is going to do with storage whose address it receives, or what a caller will have done with storage whose address it supplies, or will do with such storage once the function returns. On such implementations, given something like:
// In header
typedef union FOO_PUBLIC_UNION {
uint64_t dat[4]; // Allocate space
double dummy_align1; // Force alignment
void *dummy_align2; // Force alignment
} FOO;
void act_on_foo(FOO_PUBLIC_UNION*);
// In code
FOO x = {0};
act_on_foo(&x);
in one compilation unit, and something like:
struct FOO_PRIVATE {
int this; float that; double whatever;
};
typedef union FOO_PUBLIC_UNION { uint64_t dat[4]; struct FOO_PRIVATE priv; } FOOPP;
void act_on_foo(FOO *p)
{
FOOPP *pp = (FOOPP*)p;
pp->priv.whatever = 1234.567;
}
provided that the size of FOO and FOOPP match, the behavior of calling an external function from the first compilation unit would be defined as allocating sizeof(FOO) bytes, zeroing them, and passing their address to act_on_foo, whose behavior would then be defined as acting upon the bytes to which it receives an address, without regard for how they got their values or what the caller would do with them later.
Unfortunately, even though almost every implementation should be capable of producing behavior consistent with calling a function it knows nothing about, there is no standard way of indicating to a compiler that a particular function call should be viewed as "opaque". Implementations intended for purposes where that would be useful could and typically did support such semantics with "ordinary" function calls whether or not the Standard required that, and such semantics would offer little value on implementations intended only for purposes where they wouldn't be useful. Unfortunately, this has led to a Catch 22: there's no reason for the Standard to mandate things implementations would be free to do, with or without a mandate, in cases where they're useful, but some compiler writers treat the Standard's lack of a mandate as an encouragement to deny support.

typedef opaque pointer to opaque pointer

I got the following code:
// file external_module.h
typedef externaldata * externalhdl; // opaque pointer
externalhdl external_Create();
// file internal_module.h
typedef internaldata * internalhdl; // opaque pointer
internalhdl internal_Create();
What i would like to do is to use an opaque pointer of a external module as a opaque pointer inside of my module to save unessasary allocs. Currently my workaround implimentation is:
typedef struct {externalhdl e} internaldata;
internalhdl internal_Create()
{
internalhdl p = (internaldata*) malloc (sizeof(internaldata));
p.e = external_Create();
return p;
}
What I would like to do is use something like:
typedef ??? internaldata; //Don't know how
internalhdl internal_Create()
{
return external_Create();
}
From my point of view it should be possible since both are pointer but I need to get it warning free? Thanks for your help.
The most important thing you need to consider in my opinion, is that you will gain absolutely nothing but darkenss in doing something like this, and that you want to typedef a pointer to another type of pointer. If it is an opaque poitner, it doesn't make sense to typedef it also because you will never access the members of the underlying structure, it might very well be passed as a void * pointer, but when you allocate it, you MUST know it's type because the compiler needs to know it's size and layout in order to allocate it correctly (aligning it correctly for example would be impossible otherwise).
If you don't want to repeatedly use the sizeof operator to allocate the correct size there are two possible approaches1
Use a macro
#define allocate(x) x = malloc(sizeof(*x))
and then
my_type *x;
allocate(x);
but this is horrible and unclear.
Use an allocation function,
my_type *
my_type_alloc()
{
return malloc(sizeof(my_type));
}
such that
my_type *x;
x = my_type_allocate();
this is clean and simple, and you can't do it wrong.
Note that returning the appropriate pointer type just ensures that you will not accidentally do something that might cause undefined behavior, but allocation functions can simply return void * and they will work, that is why I did not cast malloc()'s return value.
Syntax sugar is something that you must be very careful with, because somtimes it looks like you simplified and improved syntax when what you did was hide vital information from the fellow programmer that will read your code, that programmer could even be yourself some time after writing the code.
And your workaround is actually causing one unecessary allocation. In fact, when you finally understand poitners, you will then really avoid unnecessary allocations by not copying data when you will only read from it.
1In both cases, you should check for NULL after the allocation is performed to ensure you can access such pointer without causing undefined behavior
It would seem you are on the right track with the design, it is just the implementation that's questionable. As mentioned in comments, you should never hide pointers behind typedefs and opaque pointers is no exception to this. If the caller believes that these are allocated variables, they may decide to do stupid things like this:
set_obj(obj1, "foo"); // set private data to something
memcpy(&obj2, &obj1); // take a hardcopy of the data (or so we thought)
set_obj(obj1, "bar"); // set private data to something else
print_obj(obj2); // prints "bar", wtf!!!
So stop hiding the pointers.
With some slight modifications you should get the code to work as expected:
external.h
typedef struct external_t external_t;
external_t* external_create (/* parameters here */);
external.c
#include "external.h"
external_t* external_create (/* parameters here */)
{
external_t* ext = malloc(sizeof *ext);
/* initialize stuff here */
return ext;
}
internal.h
#include "external.h"
typedef struct internal_t internal_t;
internal_t* internal_create (/* parameters here */);
internal.c
#include "internal.h"
struct internal_t
{
external_t* ext;
};
internal_t* internal_create (/* parameters here */)
{
internal_t* inter = malloc(sizeof *inter);
inter->ext = external_create (/* parameters here */);
if(inter->ext == NULL)
{
return NULL;
}
/* initialize stuff here */
return inter;
}
The caller will have to use pointers too.
Also, there is no need to cast the result of malloc. Beat the dead horse here:
Do I cast the result of malloc?.

How can a function create a struct?

One of my assignments for the C Programming course was define a function called create_card. This function receives a suit character and an a card value, and returns a card_t struct.
Question: How is a function supposed to create a struct? Can't it only create values for the struct? Did I misinterpret the meaning of the question or was the assignment written down wrong?
This is an example of a function returning a struct.
struct test {
int a;
};
struct test Fun(int k) {
struct test d;
d.a=k;
return d;
}
Replace struct test with the name of your struct and the definition of struct test with your struct's definition.
How to use
int main() {
struct test Test=Fun(6);
printf("%d",Test.a); // prints '6'
return 0;
}
You can either return a struct from a function like in ForceBru's answer, or you can create a struct in C dynamic memory (a.k.a. the heap), using malloc, and return a pointer to it, e.g.
struct foo_st {
int num;
const char* str;
};
struct foo_st*
/* the second argument s should practically be a literal string */
make_foo (int n, const char* s) {
struct foo_st* p = malloc(sizeof(struct foo_st));
if (!p) { perror("malloc foo"); exit(EXIT_FAILURE); };
p->num = n;
p->str = s;
return p;
}
Your main (or some other function) might later do struct foo_st*fooptr = make_foo(32, "abc"); but someone should call free(fooptr) (or at least, free the address which has been inside fooptr).
Of course, you should never forget to free a malloc-ed pointer when it becomes useless. Be afraid of memory leaks, buffer overflow and undefined behavior. Read more about malloc(3) & free.
BTW, in practice you should decide of who is responsible for free-ing memory. In the above make_foo example, the second parameter to make_foo is supposed to be a literal string (if it is malloc-ed e.g. using strdup(3), you'll need to free it elsewhere, and that becomes very messy).
In practice you should document the conventions about who is responsible to free some dynamically previously mallocated memory. You might want to use valgrind (if your system has it), and, if using a recent GCC compiler, its -fsanitize=address option to hunt memory related bugs. Very often, you happen to code both making and destroying functions (like here or here).
You might want to read about garbage collection (at least, to understand the concepts, such as reference counting, and the terminology). Perhaps you'll later want to use Boehm's conservative garbage collector.

Pointer to a struct as a parameter, members referenced within function produce strange values

I'm tasked with adding the quick-fit allocation algorithm to MINIX, and as such need to use structures a lot. However, I came accross something for which I cannot find any resources on a solution.
The below code is a quick example I made to demonstrate the issue I have met with.
#include <stdlib.h>
#include <stdio.h>
struct some_struct {
int h_count;
};
void why();
struct some_struct * myStruct;
int main(){
myStruct = (struct some_struct *) malloc(sizeof(struct some_struct));
myStruct->h_count=0;
printf("%d\n", myStruct->h_count);
why(&myStruct);
return 0;
}
void why(struct some_struct * t_some_struct){
printf("%d\n", t_some_struct->h_count);
}
The output of the printf in the function why is different from the output given in main. The value printed by why is a seemingly random number that changes every time the program is ran.
Output:
0
7870280
Press any key to continue . . .`
The 7870280 changes on every run. I would assume it is printing some kind of memory value or something, but that's just a guess as I have no idea really.
As such, I thought I'd ask here for the benefit of others alongside myself:
Why does this occur?
Is my syntax the issue here?
How do I use a pointer to a structure as a parameter for some function, then reference the given structure's members in the scope of the function? (I'd like to use h_count for t_some_struct as 0)
Thanks
The function why expects a pointer whereas you are passing a pointer to pointer. Call as
why(myStruct); (by the way, myStruct is a global variable, so passing is a bit superfluous here). Rest of your accessing the struct member is fine.
Not directly related but some general suggestions:
1) Use standard prototype for main() such as int main(int argc, char*argv[])
2) Casting the result of malloc is needless and error-prone.

C: how to manage a large structure?

In C:
I am trying to use a structure containing a large array, and I have a stack overflow error while declaring it. I guess (correctly?) that I don't have enough memory in the stack, and therefore, I should use the heap (I don't want to change my stack memory size, as the code will be used by others). Could anyone show me a way to do it simply? Or should I use something else than a structure?
My code - definitions.h:
#define a_large_number 100000
struct std_calibrations{
double E[a_large_number];
};
My code - main.c:
int main(int argc, char *argv[])
{
/* ...
*/
// Stack overflows here:
struct std_calibrations calibration;
/* ...
*/
return (0);
}
Thank you for your help!
A couple of options:
Use malloc(3) and free(3) to dynamically allocate your structure at runtime. This option is what you're talking about when you say you "should use the heap."
struct std_calibrations *calibration = malloc(sizeof *calibration);
and later,
free(calibration);
Give the structure static storage duration. Either add a static keyword or make it global. This option may change some semantics about how you use the structure, but given your example code, it should be fine.
Change the member E to be a double* and malloc() memory for it:
struct std_calibrations calibration;
calibration->E = malloc(sizeof(*calibration->E) * a_large_number);
and remember to free(calibration->E); when no longer required. It would be possible to extend struct std_calibrations, if desired, to contain the number of elements in E so a user of struct std_calibrations could decide how many elements they require.

Resources