I'm a bit new to C, and have been working on a project when I came across a weird behavior which I'd love to understand. (Probably something I'm missing).
I have the following structs:
typedef struct {
char *name;
int status;
int strength;
} Pig;
typedef struct {
char *name;
char color[10];
int injuryPower;
int penType;
} Bird;
When I allocate the pig, like this, it works normally:
Pig *pig_1 = malloc(sizeof(Pig *));
pig_1->status = 2;
pig_1->strength = 7;
pig_1->name = malloc(sizeof(char) * 11);
pig_1->name = "PigA\0";
But when I allocate the bird, in a similar manner, I have this weird behavior:
Bird *bird_1 = malloc(sizeof(Bird *));
1) bird_1->penType = 2;
2) bird_1->injuryPower = 5;
3) bird_1->name = malloc(sizeof(char) * 6);
bird_1->name = "BirdA\0";
bird_1->color[0] = 'R';
bird_1->color[1] = 'e';
bird_1->color[2] = 'd';
bird_1->color[3] = '\0';
In line (1) pen type is getting defined to 2.
In line (2) pen type is still 2.
In line (3) pen type gets changed according to the value I define in the bracets, so in this example it'll change to 35.
I am using Cygwin 64 bit as my compiler.
Could someone please explain what I am missing here, why is the value of pen type changing even though I am not altering it?
Is it due to malloc? Am I doing something incorrectly?
Thanks a lot!
Pig *pig_1 = malloc(sizeof(Pig *));
...
Bird *bird_1 = malloc(sizeof(Bird *));
You're allocating the size of a pointer not the size of the structure.
Pig *pig_1 = malloc(sizeof(Pig));
...
Bird *bird_1 = malloc(sizeof(Bird));
Will reserve enough space for the whole structure.
Because you are only allocating enough memory for the first member of your structure (also a pointer), the other members are in an area of memory that could be reserved for other variables. What you are seeing is the value of another variable being changed and reflected in your structure.
Related
//whether this code block on my textbook is wrong?
//I tried but failed to run and terminal shows segmentation fault.
typedef struct{
_I num;
_u32 p[];
}_BUF;
_BUF create_buf(_I size){
void *p = malloc(size + sizeof(_BUF)));
_BUF *pbuf; // a pointer to _BUF
pbuf->p = p; // pbuf->p directly points allocated memory.
pbuf->num = size;
return pbuf;
}
The flexible array member p of the _BUF type is not a pointer. That array is always located immediately after the num member (with possibly a fixed amount of padding in between). It is not possible to assign to an array object; you cannot make that array refer to memory somewhere else.
The malloc(size + sizeof(_BUF)) allocates the memory for both at once. So a correct implementation of this function would simply be
typedef struct{
_I num;
_u32 p[];
}_BUF;
_BUF *create_buf(_I size){
_BUF *pbuf = malloc(size + sizeof(_BUF)));
pbuf->num = size;
return pbuf;
}
There is no need for an intermediary void *; even though malloc returns void *, you can and should convert the return value directly to the type you actually want, and no cast is required.
And, as Craig Estey points out, returning a _BUF by value makes no sense here; it needs to be a pointer. Hopefully that was just a typo.
If the code you put in your question is really copied correctly from your textbook, then your textbook is talking nonsense, and you should probably get a better one.
I'm stuck, maybe on a very simple question.
In university we have to make our own malloc-function in C. I only have a problem when saving the pointer Address on the dereferenced pointer. Im working on heap and there is enough memory left.
void *actual_pointer = sbrk(sizeof(Node));
*(char*)actual_pointer = 'O';
actual_pointer = actual_pointer+sizeof(char);
*(char*)actual_pointer = 'K';
actual_pointer = actual_pointer+sizeof(unsigned int);
*(unsigned int*)actual_pointer = size;
actual_pointer = actual_pointer+sizeof(unsigned int);
*(unsigned int*)actual_pointer = 0;
actual_pointer = actual_pointer+sizeof(unsigned int);
*actual_pointer = actual_pointer;
The last line doesn't work. I tried everything. Isn't it possible to store some pointer Address to the dereferenced pointer?
typedef struct _Node_
{
char checkCorruption_[2];
unsigned int size_;
unsigned int status_;
char *location_;
struct Node *next_;
struct Node *prev_;
} Node;
This is the structure of my double-linked list representing the momory structure.
My Idea was the following:
We need to make a simple mallocfunction. From main function for example data[1] = malloc(100 * sizeof(int)) is called. Then I will create in the mallocfunction one Node and store the "checkCorruption"-Value 'OK' in it. After it the size, in my example "100 * sizeof(int)". After this I store a 0 for used or a 1 for free in it. Then I will store the location which is returned to data[0] - the storage gets reserved with sbrk(100*sizeof(int)) and begins at the location. Then i will store the Pointer to the next Node and the previous.
I always check the OK-value if some other malloc had an overflow and overwrited it - then i will exit with an error.
Is my Idea totally bullshit or is it ok?
Edit2:
When I will use now Node instead of void I can store also my location pointer to the node.
Node *actual_pointer = sbrk(sizeof(Node));
actual_pointer->checkCorruption_[1] = 'O';
printf("actual_pointer: %p\n", actual_pointer);
printf("actual_O: %c\n", actual_pointer->checkCorruption_[1]);
printf("actual_pointer_before: %p\n", actual_pointer);
actual_pointer = actual_pointer+sizeof(char);
printf("actual_pointer_after: %p\n", actual_pointer);
Output:
actual_pointer: 0x1ad4000
actual_O: O
actual_pointer_before: 0x1ad4000
actual_pointer_after: 0x1ad4028
But now I have some problems with actual_pointer = actual_pointer+sizeof(char);. This command should add the size of char to the actual_pointer but it increases the pointer with 40 bytes? I don't understand this?
Thanks in Advance,
Philipp
It is impossible to store value into a void...
Try replacing the last line with
*(unsigned int*)actual_pointer = (unsigned int*)actual_pointer
I am working on an assignment and ran into challenging problem. As far as I'm concerned and from what I've learnt the code that follows should be correct however it does not work. Basically what I am trying to is copy a string value into the variable member of a structure the is part of an array passed into a method as a pointer. What am I missing?
typedef struct
{
char * name; //variable in struct I am trying to access
} Struct;
void foo(Struct * arr) //array of Structs passed into function as a pointer
{
int i = 0;
while(i++ < 2)
{
arr[i].name = malloc(sizeof(char *)); //assigning memory to variable in each Struct
arr[i].name = strdup("name"); //copying "name" to variable in each Struct
printf("C - %s\n", arr[i].name); //printing out name variable in each Struct
}
}
main()
{
Struct * arr; //defining pointer
arr = calloc(2, sizeof(Struct)); //allocating memory so pointer can hold 2 Structs
foo(arr); //calling function foo passing pointer into function
return 0;
}
This code compiles and runs however it does not do what it is designed to do. Forgive me if it is something trivial. I am new to the language C
Two issues:
while(i++ < 2) This line changes the value of i as soon as it checks it, so your loop body will not be the same as it was checked.
arr[i].name = strdup("name"); overwrites the value of the .name pointer, causing a memory leak of the memory you malloc()'ed earlier.
Extending on 2 pointed out correctly already,
arr[i].name = strdup("name");
Even if you use following instead of above,
strcpy(array[i].name, "name");
you haven't allocated enough bytes to store the string i.e. this is wrong
arr[i].name = malloc(sizeof(char *));
// even if pointer is 8 byte here, concept isn't right
Should be something like
arr[i].name = malloc(strlen("name")+1);
// or MAX_SIZE where it is greater than the possible "name".
Or better yet, remove the malloc at all, strdup takes care of allocation itself
This is not answering your question directly, but addresses an issue to big to put into a comment...
Additional issue: You probably did not intend to allocate only a (char *) worth of memory to a variable intended to hold at least "name". Change;
arr[i].name = malloc(sizeof(char *));
to:
arr[i].name = malloc(sizeof(char)*strlen("name")+1); //+1 for '\0'
or better yet, use char *name="name";, then:
arr[i].name = malloc(sizeof(char)*strlen(name)+1);
Even more general (and better):
char *name;
name = malloc(strlen(someInputString)+1);
//do stuff with name...
free(name);
Now, you can allocate name to any length needed based on the length of someInputString.
[EDIT]
Etienz, I wanted to address one more thing, alluded to by #H2CO3 above, but not really explained, that I think might be useful to you:
Regarding your desire to have room for two structs, because you typedef'd your struct, you can simply do something like this: (but I am going to change the name you used from Struct to NAME :) The whole point being that when a struct is created as an array, you do not need to use calloc or malloc to create space for them, it is done as shown below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *name;
}NAME;
//use new variable type NAME to create global variables:
NAME n[2], *pN; //2 copies AND pointer created here
//prototype func
int func(NAME *a);
int main()
{
pN = &n[0]; //pointer initialized here
func(pN); //pointer used here (no malloc or calloc)
printf("name1 is %s\nname 2 is %s", pN[0].name, pN[1].name);
return 0;
}
int func(NAME *a)
{
char namme1[]="andrew";
char namme2[]="billebong";
//You DO have to allocate the members though
a[0].name = malloc(strlen(namme1)+1);
a[1].name = malloc(strlen(namme2)+1);
strcpy(a[0].name, namme1);
strcpy(a[1].name, namme2);
return 0;
}
I have below code. In below code the value 5 gets stored in variable a(i.e abc.a). But I would like to intialize the value in c (i.e abc.c). How to do that? My requirement is to fill the data for c not for a.
typedef struct abc
{
int a;
int b;
int c;
}abc;
typedef struct def{
int *ptr;
abc strpt;
}def;
typedef struct xyz{
int *pointer;
}xyz;
int main()
{
int *temp, tmp;
abc* ab;
tmp = 5;
temp = &tmp;
ab = (abc*)malloc(sizeof(abc));
xyz *x = (xyz*)malloc(sizeof(xyz));
def *de = (def*)malloc(sizeof(def));
x->pointer = (xyz*)temp;
ab = (abc*)x->pointer;
return 0;
}
Please help me.
I'm Affraid some serious lack of understanding pointers manifests in your code. Let me dissect it line by line to make clear where problems occur.
I numbered the statements in order to make easy references, assuming the type declarations as above.
int main()
{
int *temp, tmp;
abc* ab;
/* 1 */ tmp = 5;
/* 2 */ temp = &tmp;
/* 3 */ ab = (abc*)malloc(sizeof(abc));
/* 4 */ xyz *x = (xyz*)malloc(sizeof(xyz));
/* 5 */ def *de = (def*)malloc(sizeof(def));
/* 6 */ x = (xyz*)temp;
/* 7 */ ab = (abc*)x;
return 0;
}
First of all: You never clean up the memory allocated in 3, 4 and 5. Even for a simple test program, you should always take care of stuff like this.
Your first problem is line 6 where you blindly cast a pointer to an object of type int (4 bytes in memory) into a pointer to a structure of type xyz (4 or 8 bytes in memory, different type). What you do here is a complicated way to write x = (xyz*)&tmp;.
An action like that leads to following serious problems:
You just allocated memory in line 4. Now you overwrite this pointer with a pointer to your stack variable. Therefore you can't free the allocated memory anymore ==> Memory leak
Your newly assigned pointer to the stack variable becomes invalid after exiting the scope and can cause undefined behaviour.
Any write attempt to elements of x after line 6 can lead to corruption of the stack (and therefore undefined behaivour) due to a possible size mismatch of elements.
By line 7 you get the same problems again and even worse. The estimated sizeof(abc) is possibly 12 bytes. Accessing any element of abc after this line can lead to stack corruption again.
I still don't understand what you really are looking for but if you "have to" initialize a structure element through pointers there are a several ways:
If the struct ist known you can do it like this:
abc * ab = malloc(sizeof(abc));
if (ab != NULL) {
ab->c = 5;
// -- do other stuff
free(ab); ab = NULL;
}
If you need a pointer to the element 'c' you can do it like this:
int * c_ptr = NULL;
abc * ab = malloc(sizeof(abc));
if (ab != NULL) {
c_ptr = &(ab->c);
*c_ptr = 5;
//-- do other stuff
free(ab); ab = NULL;
}
Are you asking for this:
abc s;
s.c = 5;
That makes c 5. Or you could do thos:
abc s = {0,0,5};
That means, the first two members are initialized to 0, and third one (which is c) is initialized to 5.
Or if you've pointer, then you can do this:
abc *p = malloc(etc);
p->c = 5;
But then avoid using pointers and malloc. Use it when you really need them. In your code, I don't see any reason why you would need it. Use automatic variables, not pointers.
I think you would need to add this before return in your main() to get what you need.
ab->c = *(x->pointer);
I am using a struct and I want to initialize a maximum of 10 ports. However, when the program is running it could be a lot less, we don't know until run-time. However, this will be the max. I have never done struct like this before, as I normally dynamically allocate using calloc and delcare like this *ports as the value type.
However, I can't understand this
*ports[MAX_PORTS]. Am I creating 10 pointers that point to port objects?
And
*ports = (struct port_t*) calloc(2, sizeof(*ports));
Looks like I am allocating a single pointer that points to 2 port objects allocated on the free store?
I can't understand why I am using a dot operator with a arrow operator?
ports[0]->port_id = 20;
printf("port_id: %d\n", ports[0]->port_id);
#include <stdio.h>
#include <stdlib.h>
#define MAX_PORTS 10
struct port_t
{
int port_id;
char name;
} *ports[MAX_PORTS];
int main(void)
{
*ports = (struct port_t*) calloc(2, sizeof(*ports));
ports[0]->port_id = 20;
printf("port_id: %d\n", ports[0]->port_id);
return 0;
}
normally, what I have done in the passed is this:
struct port_t
{
int port_id;
char name;
} *ports;
ports = (struct port_t*) calloc(2, sizeof(*ports));
And then assign with either of the following below. However, the previous programmer has declared everything like I have displayed at the top so I can't change anything.
ports[0].port_id = 10;
ports->port_id = 10;
Many thanks for any suggestions,
Your first code block has
struct port_t
{
int port_id;
char name;
} *ports[MAX_PORTS];
which is an array of pointers. This means later when you use
ports[0]->port_id
you are dereferencing the first pointer in the array. There is also some ugliness surrounding the size of what you are actually calloc'ing. You're actually replacing your array of 10 with an array of 2. What you've got there is generally ugly and error prone.
I believe your intentions are more along the lines of:
struct port_t
{
int port_id;
char name;
} *ports;
int main(void)
{
*ports = (struct port_t*) calloc(2, sizeof(*ports));
ports[0].port_id = 20;
printf("port_id: %d\n", ports[0].port_id);
return 0;
}
Since you are using C99, you could avoid calloc()/malloc(), if you really want to by using C99's variable array declaration.
port_t array_on_mains_stack[some_runtime_port_count];
ports = array_on_mains_stack;
The trick there is that since it is on the stack, it is only valid from that function and any function called by it. Once you return from that function, it is of course freed.
*ports[MAX_PORTS]. Am I creating 10 pointers that point to port objects?
Yes, you're making an array of ten pointers
*ports = (struct port_t*) calloc(2, sizeof(*ports));
...but this line is nonsense. It's the same as this:
ports[0] = (struct port_t*) calloc(2, sizeof(port_t));
ie. You're setting the first pointer to point to enough memory for two ports.
For such a small thing it would make much more sense to make ten ports but not use them all:
#define MAX_PORTS 10
struct port_t
{
int port_id;
char name;
} ports[MAX_PORTS];
/* number of ports in use */
int numPorts = 0;
int main(void)
{
numPorts = 3;
for (int i=0; i<numPorts; i++) {
ports[i].port_id = i;
printf("port_id %d: %d\n", i, ports[i].port_id);
}
return 0;
}
ports is and array of pointers to port_t objects, so by doing ports[0] you get a pointer, not an object, and you need to access it with ->
Grab a good resource on pointers in C and read it from cover to cover. There are also tutorials on reading C declarations. You won't be able to understand this topic by getting answers to random questions.
Here's a link worth reading.