I have the following piece of code which I would expect to fail but seems to be working correctly. I'm confused by why this is not causing some sort of segmentation fault.
#include <stdio.h>
#include <stdlib.h>
struct entry {
int foo;
};
struct table {
int size;
struct entry* entries;
};
typedef struct table *Table;
typedef struct entry Entry;
int main() {
Table table = malloc(sizeof(struct table));
table->entries = malloc(sizeof(struct entry) * 1);
(table->entries)[5].foo = 5;
for (int i = 0; i < 10; i++) {
printf("Entry #%d: %d\n",i,(table->entries)[i].foo);
}
}
I would have expected that since I only malloced enough space for one entry in table->entries, accessing any index other than 0 would be out of bounds. But when I run this program it prints out 5 for as the foo value of the entry at index 5, and the rest as 0, which is the correct behavior. Why is this not failing?
Someone else will say it better, but Undefined Behavior is undefined.
It's not defined. It might work. It might not.
It all depends what is in those memory locations.
You wrote one bad location. You read some others. You happened to not hit anything
too important.
You wrote one word well past your malloc'ed area. Perhaps if you did more computations
that would cause trouble because you wrote into malloc's data structures. Maybe not.
You are accessing out of bounds, but that merely invokes 'undefined behaviour'. Anything may happen when you invoke 'undefined behaviour'. One possibility is that the program crashes; another is that the program does not crash and appears to be OK. Either is possible; it is even possible for it sometimes to crash and sometimes not crash.
If you tried more memory allocation, or tried freeing memory, you'd be more likely to see that things have gone wrong. However, even that's not guaranteed; you may have missed all the sensitive information (the bytes that are used by malloc() et al to determine which memory is allocated and which is not).
You can write:
table->entries[i].foo
You don't need the parentheses around (table->entries)[i].foo, though they're harmless except that they suggest a neophyte was coding.
Its not failing because despite you are writing to unallocated memory, this memory is perfectly inside the legal HEAP space. But sinse you didn't declare to the memory manager that you are using that memory space, a future malloc() may try to alloc to the same area, and you will get overlapping buffers and undefined behaviour.
This is undefined behavior that you are accessing memory location which is not 'yours'. You have writern some thing in memory which is not allocated by you, corrupting that memory location.
#include <stdio.h>
#include <stdlib.h>
struct entry {
int foo;
};
struct table {
int size;
struct entry* entries;
};
typedef struct table *Table;
typedef struct entry Entry;
int main() {
Table table =(table)malloc(sizeof(struct table));
table->entries =(entry*)malloc(sizeof(struct entry) * 10);
(table->entries)[5].foo = 5;
for (int i = 0; i < 10; i++) {
printf("Entry #%d: %d\n",i,(table->entries)[i].foo);
}
}
First, you need to convert the (void*) type into the pointer type you want when using malloc. Second, you only allocate entries pointers, which means, when you use (table->entries)[5].foo, you might access memory illegal, so it's a dangerous behavior. Finally, you need to initialize foo before you print it. You need to obey the rules, do not write codes like that.
Related
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.
I am fairly new to C, and am having trouble figuring out how to allocate contiguous memory to an array of structs. In this assignment, we are given a shell of the code, and have to fill in the rest. Thus, I cannot change the variable names or function prototypes. This is what has been given to me:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct student {
int id;
int score;
};
struct student *allocate() {
/* Allocate memory for ten students */
/* return the pointer */
}
int main() {
struct student *stud = allocate();
return 0;
}
I'm just not sure how to go about doing what those comments say in the allocate function.
The simplest way to allocate and initialize the array is this:
struct student *allocate(void) {
/* Allocate and initialize memory for ten students */
return calloc(10, sizeof(struct student));
}
Notes:
calloc(), unlike malloc() initializes the memory block to all bits zero. Hence the fields id and score of all elements in the array are initialized to 0.
It would be a good idea to pass the number of students as an argument to the function allocate().
It is considered good style to free() allocated memory when you no longer need it. Your instructor did not hint that you should call free(stud); before returning from main(): while not strictly necessary (all memory allocated by the program is reclaimed by the system when the program exits), it is a good habit to take and makes it easier to locate memory leaks in larger programs.
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.
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.
Coding in C:
typedef struct {
char *string;
int one;
int two;
} Example;
... elsewhere:
Example *new = (Example *)malloc(sizeof(Example*));
new->string = strdup(otherstring); //no problem here
new->one = 5; //valgrind says that there is an invalid write of size 4.
My program runs fine, I just can't make valgrind happy. And that probably means I will have some other error elsewhere.
I guess I don't have to declare a pointer to the structure, (i.e., I could call "Example new" instead), but I'm stuck finding out how to allocate memory on the heap because I will need to access "new" from other parts of the program.
Am I making a mistake in the above few lines? Or is my error likely to be somewhere else? This is the first memory error that valgrind reports.
EDIT: accidentally had int *s instead of ints in my struct. Fixed.
I see various problems here. First of all, this:
Example *new = (Example *)malloc(sizeof(Example*));
doesn't allocate the right amount of memory (and you don't need the cast). You want this:
Example *new = malloc(sizeof(Example));
Then, you say this:
new->one = 5;
and that's assigning an int to an int*; that's not a good idea and valgrind rightly complains about it. If your struct is properly declared, then you want this:
new->one = malloc(sizeof(int)); /* The other malloc doesn't allocate this, you have to. */
*(new->one) = 5;
I suspect (as you say that everything works) that you really mean to declare your struct like this:
typedef struct {
char *string;
int one;
int *two;
} Example;
but there isn't enough information to be certain. Then you probably still have similar issues with new->two.
Example *new = (Example )malloc(sizeof(Example));
Should be:
Example *new = (Example *)malloc(sizeof(Example);
You have to allocate the whole struct not just a reference to it. Sometimes the program runs just because you get lucky.
Try this instead (just cut, paste, and run):
Example *new = (Example *)malloc(sizeof(Example)); //This is the correct method as pointed out by Bob, otherwise you're allocating only enough space to fit a memory location vs the struct
new->string = strdup(otherstring); //this is okay
new->one = (int*)malloc(sizeof(int));
*(new->one) = 5; //You want to assign the value 5 to the new->one memory location, not assign new->one pointer the value of 5!!!