Unexpected pointer change after deferenced pointer affectation - c

One of my pointer is being changed after I deference it and affect it a value. I don't understand why, especially since the code in that function is runned multiple times but work most of the time. Here is the code :
typedef struct s_freeList
{
int sSize;
struct s_freeList *next;
struct s_freeList *back;
int *eSize;
} t_freeList;
void *addNode(void *addr, size_t size)
{
t_freeList *freeList;
// Working stuff
freeList = (t_freeList *)addr;
freeList->sSize = size * -1;
freeList->next = ((t_freeList *)g_startAddr)->next;
freeList->back = g_startAddr;
((t_freeList *)g_startAddr)->next->back = freeList;
((t_freeList *)g_startAddr)->next = freeList;
// Not working stuff
printf("addr = %p\nsize = %d\n", addr, (int)size);
freeList->eSize = addr + size - 4;
printf("freelist->esize = %p\n", freeList->eSize);
*(freeList->eSize) = size * -1;
printf("freelist->esize = %p\n\n", freeList->eSize);
return (collapseNodes(addr));
}
Here is the output with the address :
addr = 0x1647020
size = 32
freelist->esize = 0x164703c
freelist->esize = 0xffffffe00164703c

From your printf output, you're running on a platform with 64-bit pointers. Each pointer has size and, importantly, natural alignment of 8 bytes, which gives the following layout of your structure (offsets are in decimal):
00 sSize;
04 <padding>
08 *next;
16 *back;
24 *eSize;
32 <total size>
You're setting freeList->eSize = addr + size - 4, which, with size = 32, just happens to overlap with the higher portion of eSize field itself.
If you're going to do the address arithmetic, try to use the compiler-provided introspection facilities such as sizeof and offsetof wherever possible. They may reduce the incidence of such errors and will make the code more readable and more portable.
(Or, better yet, avoid the address arithmetic at all).

I have not tried the code, but here is what I think its happening. The following few lines assign values for the new node and insert it into the list:
// Working stuff
freeList = (t_freeList *)addr;
freeList->sSize = size * -1;
freeList->next = ((t_freeList *)g_startAddr)->next;
freeList->back = g_startAddr;
((t_freeList *)g_startAddr)->next->back = freeList;
((t_freeList *)g_startAddr)->next = freeList;
Clearly, addr is a pointer to the newly inserted node. Now this is the interesting thing:
freeList->eSize = addr + size - 4;
assuming that size == sizeof(struct s_freeList) then what you are basically doing is assigning eSize its own address + 4 bytes! I think this is because the sizeof(int *) happens to be 8 bytes and in memory your structure probably looks like this:
----------
|sSize | <-- addr
----------
|next |
----------
|back; |
----------
|eSize; | <-- addr + size - 4 probably because sizeof(int *) == 8 bytes.
----------
So when you do:
*(freeList->eSize) = size * -1;
you are modifying the value of eSize since it points to itself!
Edit: I just when over the code and output again and what atzz says is right, you are probably running a 64-bit machine, but the idea is still the same, eSize is overwriting itself...

Related

memcpy issue when copying a pointer to a struct

I'm having trouble understanding why the 2 board pointers point to the same memory location, following is my situation in my game.c:
int game_state_transition(const struct state * s0, const struct move * m, struct state * s1) {
memcpy(s1, s0, sizeof(struct state));
memcpy(s1->board, s0->board, sizeof(struct move ***));
if (game_update(s1, m)){
printf("%p\n", s1->board);
printf("%p\n", s0->board);
game_print(s0);
s1->next = s0;
return 1;
}
return 0;
and here's my game.h:
struct state {
struct player * current_player;
struct move *** board;
enum game_status status;
const struct state * next; };
I understand that after the first memcpy the 2 board pointers point to the same location in memory, but I do not understand the behavior of the second.
Thanks for the help
First memcpy call makes what s1 points to, be the same as what points to s0. From this point s0->board and s1->board has the same pointer value
memcpy(s1, s0, sizeof(struct state));
example:
before call:
s0->player = 0x000100
s0->move = 0x000200
s0->status = 1
s0->state = 0x000300
s1->player = 0x000400
s1->move = 0x000500
s1->status = 2
s1->state = 0x000600
after call:
s0->player = 0x000100
s0->move = 0x000200
s0->status = 1
s0->state = 0x000300
s1->player = 0x000100
s1->move = 0x000200
s1->status = 1
s1->state = 0x000300
For the second memcpy there are more issues.
memcpy(s1->board, s0->board, sizeof(struct move ***));
First of, you send the pointer, so the correct term would be sizeof(struct move **), but it will yield the same size, since all pointers have the same size.
If your intention is to make a new copy (in order to preserve the previous state), you would need to allocate memory first.
It is not often we see three stars in C programming, but it does happen. It all depends on the logic needed, and how many levels of changes should be possible in the call-stack. Most common is 1 and 2 (giving you the direct pointer, and a reference to a pointer that can be changed from an external point)

Malloc behaving strangely when allocating space for ints

Probably I just lack understanding of how malloc works, but I don't see an error with my code:
int amount_integers = 2;
int *pointer_to_allocated_memory = (int*)malloc(amount_integers * sizeof(int));
for (int i = 0; i < amount_integers; i++)
{
int *address = &(pointer_to_allocated_memory)[i * sizeof(int)];
*(address) = 0;
}
I'd like to initialize memory for an arbitrary amount of integers (amount_integers could be something else than 2). However, the malloc in line 2 seems to misfunction. MSVC's debugger will break at this point (without having defined a breakpoint). When continuing, it will encounter an access writing violation at line 6 (*(address) = 0;) when i is 1.
What I think I'm accessing:
v pointer_to_allocated_memory[0 * sizeof(int)]
... | sizeof(int) | sizeof(int) |
^ pointer_to_allocated_memory[1 * sizeof(int)]
These should be allocated. Why does the application crash?
The array index is not indexing bytes but array elements, in your case ints:
int *address = &(pointer_to_allocated_memory)[i];
valid values for i are 0 and 1
Because you misunderstand how pointer arithmetic works. It doesn't work with bytes, it works with chunks of memory of sizeof(T) bytes, T being the pointer's pointed type. So
int *address = &(pointer_to_allocated_memory)[i * sizeof(int)];
should be
int *address = &ptr[i];
instead. (Also note the lack of superfluous parenthesizing and simpler name...)
By the way, casting malloc is harmful.

Adding `int` to address causes int to be added 4 times

For a course about the functioning of operating systems, we had to write a malloc/free implementation for a specific sized struct. Our idea was to store the overhead, like the start and end of the specified (static) memory block our code has to work in, in the first few addresses of that block.
However, something went wrong with the calculation of the last memory slot; We're adding the size of all usable memory slots to the address of the first usable memory slot, to determine what the last slot is. However, when adding the int sizeofslots to the address of currentslot, it actually adds sizeofslots 4 times to this address. Here's the relevant code:
/* Example memory block*/
/* |------------------------------------------------------------------------------|*/
/* | ovr | 1 t | 0 | 1 t | 1 t | 1 t | 0 | 0 | 0 | 0 | 0 | 0 | 0 |*/
/* |------------------------------------------------------------------------------|*/
/* ovr: overhead, the variables `currentslot`, `firstslot` and `lastslot`.
* 1/0: Whether or not the slot is taken.
* t: the struct
*/
/* Store the pointer to the last allocated slot at the first address */
currentslot = get_MEM_BLOCK_START();
*currentslot = currentslot + 3*sizeof(void *);
/* The first usable memory slot after the overhead */
firstslot = currentslot + sizeof(void *);
*firstslot = currentslot + 3*sizeof(void *);
/* The total size of all the effective memory slots */
int sizeofslots = SLOT_SIZE * numslots;
/* The last usable slot in our memory block */
lastslot = currentslot + 2*sizeof(void*);
*lastslot = firstslot + sizeofslots;
printf("%p + %i = %p, became %p\n", previous, sizeofslots, previous + (SLOT_SIZE*numslots), *lastslot);
We figured it had something to do with integers being 4 bytes, but we still don't get what is happening here; Can anyone explain it?
C's pointer arithmetic always works like this; addition and subtraction is always in terms of the item being pointed at, not in bytes.
Compare it to array indexing: as you might know, the expression a[i] is equivalent to *(a + i), for any pointer a and integer i. Thus, it must be the case that the addition happens in terms of the size of each element of a.
To work around it, cast the structure pointer down to (char *) before the add.
When you add an integer to a pointer, it increments by that many strides (i.e. myPointer + x will increment by x*sizeof(x). If this didn't happen, it would be possible to have unaligned integers, which is many processor architectures is a fault and will cause some funky behaviour, to say the least.
Take the following as an example
char* foo = (char*)0x0; // Foo = 0
foo += 5; // foo = 5
short* bar = (short*)0x0; // Bar = 0; (we assume two byte shorts)
bar += 5; // Bar = 0xA (10)
int* foobar = (int*)0x0; // foobar = 0; (we assume four byte ints)
foobar += 2; // foobar = 8;
char (*myArr)[8]; // A pointer to an array of chars, 8 size
myArr += 2; // myArr = 0x10 (16). This is because sizeof(char[8]) = 8;
Example
const int MAX = 3;
int main ()
{
int var[] = {10, 100, 200};
int i, *ptr;
/* let us have array address in pointer */
ptr = var;
for ( i = 0; i < MAX; i++)
{
printf("Address of var[%d] = %x\n", i, ptr );
printf("Value of var[%d] = %d\n", i, *ptr );
/* move to the next location */
ptr++;
}
return 0;
}
Output::
Address of var[0] = bfb7fe3c
Value of var[0] = 10
Address of var[1] = bfb7fe40
Value of var[1] = 100
Address of var[2] = bfb7fe44
Value of var[2] = 200
You can deduce from the example that, a pointer increments itself by "Number Of Bytes" = "Size of the type it is pointing to". Here it is, Number Of bytes = sizeof(int). Similarly, it will increment itself 1 byte in case of char.

How to initialize the structure member with using pointer?

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);

How to access allocated memory in C?

After using malloc() to initialize 5000 bytes of memory, how would I reference the bytes in this memory space? For example, if I need to point to a starting location of data within the memory, how would I go about that?
EDIT: Does it matter what I use to point to it? I mean I am seeing people use bytes/int/char? Is it relevant?
Error I get:
You can use the subscript array[n] operator to access the index you are interested in reading/writing, like so:
uint8_t* const bytes = (uint8_t*)malloc(5000);
bytes[0] = UINT8_MAX; // << write UINT8_MAX to the first element
uint8_t valueAtIndexZero = bytes[0]; // << read the first element (will be UINT8_MAX)
...
free(bytes), bytes = 0;
char * buffer = malloc(5000);
buffer[idx] = whatever;
char * p = buffer + idx;
*p = whatever;
Malloc doesn't initialize the bits allocated by it. Use calloc() rather.
int *p = malloc (5000); // p points to the start of the dynamically allocated area.
As has been mentioned by others, you could do something like this:
int nbytes = 23; // number of bytes of space to allocate
byte *stuff = malloc(nbytes * sizeof stuff[0]);
stuff[0] = 0; // set the first byte to 0
byte x = stuff[0]; // get the first byte
int n = 3;
stuff[n] = 0; // set the nth byte to 0
x = stuff[n]; // nth byte, or in the case of some other type, nth whatever - just make sure it's a safe value, from 0 (inclusive) to the number (nbytes here) of things you allocated (exclusive)
However, a couple of things to note:
malloc will not initialise the memory, but calloc will (as mentioned by Prasoon Saurav)
You should always check to see if the memory allocation failed (see below for an example)
int nbytes = 23; // or however many you want
byte *stuff = malloc(nbytes * sizeof stuff[0]);
if (NULL == stuff) // memory allocation failed!
{
//handle it here, e.g. by exiting the program and displaying an appropriate error message
}
stuff[0] = 0; // set the first byte to 0
byte x = stuff[0]; // get the first byte
int n = 3;
stuff[n] = 0; // set the nth byte to 0
x = stuff[n]; // nth byte, or in the case of some other type, nth whatever
malloc() returns a pointer to the allocated memory:
typedef unsigned char byte;
byte * mem = malloc( 5000 );
byte val = mem[1000]; /* gets the 1000th byte */
After using malloc() to initialize 5000 bytes of memory, how would I
reference the bytes in this memory space? For example, if I need to
point to a starting location of data within the memory, how would I go
about that?
Does it matter what I use to point to it? I mean I am seeing people
use bytes/int/char? Is it relevant?
as you have seen malloc allocates a block of memory counted in bytes, you can assign a pointer to that block and depending on the pointer type the compiler knows how to reference individual elements:
unsigned char *memblob = malloc( 1024 );
short* pshort = (short*)memblob;
now if you reference the second short value i.e. *(pshort + 1) or pshort[1] the compiler knows that it needs to add 2 bytes (sizeof(short)) in order get the next element.
float* pfloat = (float*)memblob;
now if you reference the second float value i.e. *(pfloat + 1) or pfloat[1] the compiler knows that it needs to add 4 bytes (sizeof(float)) in order get the next element.
same with own defined data types:
typedef struct s
{
short a;
long b;
} mystruct_t;
mystruct_t* pstruct = (mystruct_t*)memblob;
pstruct + 1 accesses the struct at offset sizeof(mystruct_t)
so it is really up to you how you want to use the allocated memory

Resources