C Structs: Problem Initializing? Valgrind Errors - c

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!!!

Related

malloc with structs and how to access memory of malloc of struct

if i have a simple struct such as
How would i got about dynamically allocating memory for this struct using malloc?
struct Dimensions{
int height, width;
char name;
};
I um unsure on how to go about this, I have tried
struct Dimension* dim = malloc(sizeof(struct Dimensions));
Also I would like then access the height and width variable in a loop later on in my code. My first thought would be to use a pointer but im unsure on what this would exactly be.
Would it be something like
int h = *width
I'm very new to C. Thanks
The way you dynamically allocated that struct is correct:
struct Dimension* dim = malloc(sizeof(struct Dimensions));
Also I would like then access the height and width variable in a loop later on in my code.
You should first assign some value to that dim first, something like:
dim->high = 1;
dim->width = 2;
The name member you just used a char which might not be what you need. Usually it's a string: char name[100];. You can't use assignment for that string though, so use strcpy.
Then you can access that later:
int h = dim->high;
Remember once you're done with the dynamically allocated memory, you should free it:
free(dim);
return 0;

Incrementing member of struct segfaults

I'm trying to increment a value of a struct (an int) just to test a code snippet of mine (This isn't my entire code), just the point of focus of my question. I'm given the struct:
typedef struct Test Test;
typedef struct Test {
char * name;
int numOfElements;
Test * test[];
}Test;
As well as the functions:
void startFunc(Test ** newStruct) {
newStruct = malloc(sizeof(Test));
(*newStruct)->name = NULL;
(*newStruct)->numOfElements = 0;
func(newStruct);
}
void func(Test ** newStruct) {
(*newStruct)->numOfElements++;
}
//create function to later free allocated memory
However incrementing the value of numOfElements seems to segfault. Is it the fact that I didn't allocate enough memory (Since I'm using a flexible array member?)
I tried using valgrind and got a invalid read of size 8 on the (*newStruct)->name =NULL;
Which would suggest it's not malloced, Memory help here would be much appreciated,
malloc(sizeof(Test)) is intended to allocate a raw object of type Test, so conceptually it returns a Test * pointer. This pointer is assigned to newStruct, which is a Test **. This mismatch between Test * and Test ** already suggests that the malloc line is broken.
An immediate guess would be that this
newStruct = malloc(sizeof(Test));
was actually intended to be
*newStruct = malloc(sizeof(Test));
You are already scrupulously using *newStruct everywhere in your startFunc, but for some reason completely forgetting about it in the malloc line.
An arguably better way to express the same thing would be
*newStruct = malloc(sizeof **newStruct);

Dynamic array of pointer to structs - do I really need to explicitly allocate space for ea element?

I have a struct defined like this:
typedef struct
{
int num;
char letter;
}* Foo;
And an array like this:
Foo* items = malloc(sizeof(Foo) * 4);
From my understanding and from the (accepted) answer to this question Dynamic array of pointers to structs, I would expect the above line to only reserve the memory for 4 Foo items, but doesn't initialize it - i.e., if I try to access items[i]->num, I should get some kind of error.
Also, in order to insert item into this array, I should do this:
items[0] = malloc(sizeof(*items[0]));
However, I did a little test, and seems like the following code prints 1 and a just fine:
Foo* items = malloc(sizeof(Foo) * 2);
items[0]->num = 4;
items[0]->letter = 'a';
printf("items[0] = {num=%d, char=%c}\n", items[0]->num, items[0]->letter);
I'm confused. Is this the expected behavior?
Your initial malloc:
Foo* items = malloc(sizeof(Foo) * 4);
Is creating an array of 4 pointers, since Foo is a pointer type. So your second malloc:
items[0] = malloc(sizeof(*items[0]));
Makes sense, since you're allocating a struct to that pointer.
However, the assignment you're doing leads to undefined behavior because you didn't do the second malloc and therefore no space has been allocated to items[0] yet. C won't prevent you from writing to a memory location you shouldn't be writing to. And once you do that, anything can happen.
One thing that's a bit confusing here is that you used typedef to define a pointer type. That can lead to a lot of confusion since it's not apparent by looking at the type that it's a pointer. And in this case, because of how you defined Foo, you had an extra layer of pointer indirection you probably don't need.
So if you define your struct like this:
typedef struct
{
int num;
char letter;
} Foo;
Then this can be done safely:
Foo* items = malloc(sizeof(Foo) * 2);
items[0].num = 4;
items[0].letter = 'a';
printf("items[0] = {num=%d, char=%c}\n", items[0].num, items[0].letter);
Now the malloc creates an array of structs instead of an array of pointers to structs, so an additional layer of mallocs is no longer necessary.
You have to allocate structs and save its pointer to items's elements if you want to use structs. Otherwise, the item's elements are junk and access to it may cause errors.
The second test may worked fine due to the optimization which removes malloc and pass the values of items[0]->num and items[0]->letter directly to printf.
This is happening because you have reserved enough space for the Foo array and probably one element but it's not the expected behavior, there is no expected behavior in this case because what you do invokes undefined behavior.
This will fail if you add more fields to the struct, because then 2 * sizeof(void *) will not be enough. To test it, try adding 2 pointers to the struct like this1
typedef struct
{
int num;
char letter;
void *pointers[2];
} *Foo;
If you want you can do it right, and this is another reason not to typedef a pointer, this would work
typedef struct
{
int num;
char letter;
void *pointers[2];
} Foo;
Foo *foo_pointer = malloc(N * sizeof(Foo));
/* ^ this would be wrong if `Foo' were a pointer */
if (foo_pointer == NULL)
please_abort_this_do_not_continue_because_malloc_has_failed();
foo_pointer[0].num = 1;
foo_pointer[0].letter = 'a';
1It really annoys me to write this, because typedefing a pointer is never a good idea

A Simple Object System

I'm working my way through the learn c the hard way book and have run into a few issues on Exercise 19. The author said that ex19 was intended for the learners to get to know the macro in c. I have no problem in understanding the concept of that, but I just don't understand everything else. I can't understand how the object prototype is created.
Especilly,what does the following sentense mean?
Since C puts the Room.proto field first, that means the el pointer is
really only pointing at enough of the block of memory to see a full
Object struct. It has no idea that it's even called proto.
the relevant code is this:
// this seems weird, but we can make a struct of one size,
// then point a different pointer at it to "cast" it
Object *el = calloc(1, size);
*el = proto;
can anyone tell me how on earth malloc/calloc exactly works? As far as i know, it just allocate the required number of memory and return the first address. If so, how can the computer know the data struct of the allocated memory? like in the code, after Room *arena = NEW(Room, "The arena, with the minotaur");,you can do this directly arena->bad_guy = NEW(Monster, "The evil minotaur"); how does the computer know there is a bad_guy??
what on earth is the content of *el after the above two statements(Object *el = calloc(1, size); and *el = proto;)?
Any help will be appreciated!!
the link to the exercise: http://c.learncodethehardway.org/book/ex19.html
calloc has the additional feature that it fills the allocated memory with zero bytes, whereas using the equivalent malloc call would require an additional step if all or some of the allocation needs to be zero initially.
In the code
arena->bad_guy = NEW(Monster, "The evil minotaur");
the compiler knows the layout of the struct because the access is through the arena variable, which is declared as a pointer to Room, which is presumably a typedef of a struct.
For the other part, the guarantee of ordering within structs allows a limited form of inheritance in composite structs, or extended structs.
struct A {
int x;
};
struct B {
int foo;
double baloney;
};
struct B (or a pointer to it) can be cast to a (pointer to a) struct A because they both begin with an int. Of course, if you cast the other way, the struct A must have been originally a struct B or access to the baloney field will be undefined. In other words, struct B essentially begins with a struct A.
This may be easier to see if I rewrite my example like this:
struct A {
int x;
};
struct B {
struct A foo;
double baloney;
};
Now you can get a struct A out of struct B in different ways.
struct A a;
struct B b;
a = b.foo; // regular member variable access
struct A *ap = &a;
struct B *bp = &b;
ap = (struct A *)bp; // cast the pointer
ap = & b.foo; // take a pointer from the member variable
ap = & bp->foo; // take a pointer from the member variable via a pointer
All it does is to alloc 1*size bytes. There's nothing magic with malloc/calloc. He is passing the sizeof(T) to the function through that NEW macro and putting it in Object_new's size parameter. So all the function knows is the size in bytes.

Mallocing an Array in C

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.

Resources