I have this piece of code in one library I'm using and I'm wondering what it does, since I'm having problems with memory I suppose this is the reason.
So the piece of code is following:
int new_size = foo->a_size + 10;
foo->a = realloc(foo->a, new_size*sizeof(struct items));
memset(foo->a+foo->a_size, 0, 10);
foo->a is type struct items* and foo->a_size is type int.
First lines reallocate 10 blocks of new memory but now I'm wondering if memset() sets both foo->a and foo->a_size to 0 or should this set blocks from 11-20 to 0 in foo->a?
I have tried to run this code block on its own and receive only Segmentation fault
EDIT:
Question was that does the memset() set both foo->a and foo->a_size to 0 or does it set blocks from offset foo->a_size to 0 in foo->a. The latter assumption was correct but I need to also fix the memset() so the last argument is 10 * sizeof(struct items). I also edited variable names from foo->b to foo->a_size.
You are initializing 10 Bytes in foo->a(pointer) with foo->b(int) offset. In the other words you just initialized appended memory.
Example:
Lets assume foo->a is int* and is pointing to 5 ints continuous block.
+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+
You need 10 ints, so you will realloc that block to size 10 * sizeof(int) Bytes, but appended 5 * sizeof(int) Bytes are uninitialized.
+---+---+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | ? | ? | ? | ? | ? |
+---+---+---+---+---+---+---+---+---+---+
So by doing
memset(pointerToFirstByte + Offset, 0, 5 * sizeof(int));
You will init these appended bytes to 0.
+---+---+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+---+---+
^---^---^---^---^------ Initialized to 0
The line in question sets 10 bytes starting with an offset by foo->b from foo->a to 0. The offset is in steps the size of the structure items. We don't have enough information to further explain this, but my speculation is that foo->a is a pointer to a dynamically allocated array of the structure and here we are setting the fields of part of it(possibly one element?) to 0.
So these 2 lines increase foo->a by 10 lots of whatever struct items is.
int new_size = foo->b + 10;
foo->a = realloc(foo->a, new_size*sizeof(struct items));
This sets 10 bytes of memory of foo->a offset by foo->b * sizeof(struct items) to 0
memset(foo->a+foo->b, 0, 10);
which isn't probably enough as it's unlikely struct items is just 1 byte in size. What you should be doing is clearly 10 lots of struct items like this.
memset(foo->a+foo->b, 0, 10*sizeof(struct items));
The memset in the code fragment initializes 10 bytes in the newly allocated part of foo->a to 0. There are multiple problems in this code:
You do not test for realloc() failure.
You overwrite foo->a with the return value from realloc(). If realloc() fails, the block previouly pointed to by foo->a is still allocated but potentially unreachable, a memory leak.
The space set to 0 is most probably too small.
Initializing to all bits 0 might not be appropriate for the structure items.
You do not update foo->size.
Here is an improved version:
size_t new_size = foo->a_size + 10;
struct items *newp = realloc(foo->a, new_size * sizeof(*foo->a));
if (newp == NULL) {
// handle the error
} else {
memset(newp + foo->a_size, 0, (new_size - foo->a_size) * sizeof(*foo->a));
foo->a = newp;
foo->a_size = new_size;
}
memset(foo->a+foo->b, 0, 10);
This line sets the 10 Bytes of Foo->a to 0.
foo->a + foo->b is a offset value in it.
Related
I'm thinking about re-implementing the malloc(3) function (as well as free(3), realloc(3) and calloc(3)) using mmap(2) and munmap(2) syscalls (as sbrk(2) is now deprecated on some operating systems).
My strategy to allocate memory blocks on the page returned by mmap(2) would be to store metadata right before the block of data. Thus the metadata could consist of 3 attributes :
is_free : a char (1 byte) to tell if the block is considered free or not;
size : an size_t (4 bytes) with the size of the block in term of bytes;
next : a pointer (1 byte) to the next block's metadata (or to the next page first block if there's no more space after the block).
But as I can't use malloc to allocate a struct for them, I would simply consider putting 6 bytes of metadata in front of the block each time I create one :
+---------+---------+--------+------------------+---------+---------+--------+---------+---
| is_free | size | next | Block1 | is_free | size | next | Block2 | ...
+---------+---------+--------+------------------+---------+---------+--------+---------+---
| 1 byte | 4 bytes | 1 byte | n bytes | 1 byte | 4 bytes | 1 byte | m bytes | ...
+---------+---------+--------+------------------+---------+---------+--------+---------+---
The question is :
How can I be sure the user/process using my malloc won't be able to read/write the metadata of the blocks with such architecture ?
Eg: With the previous schema, I return the Block1's first byte to the user/process. If he/it does *(Block1 + n) = Some1ByteData he/it can alter the metadata of the next block which will cause issues with my program if I try to allocate a new block later on.
On the mmap(2) man page I read that I could give protection flags for the pages, but if I use them, then the user/process using my malloc won't be able to use the block I give. How is it achieve in the real malloc ?
PS: For the moment I don't consider thread-safe implementation nor looking for top-tier performances. I just want something strong and functionnal.
Thanks.
I'm trying to print a dynamic 2D array in C, the problem is that with the code it prints fine the first time but if its printed anymore times its missing the bottom row.
This is the code I'm working with:
void display_board( int height, int width, char** gameBoard ) {
int i;
char *rowString;
rowString = malloc(((width*2)+1) * sizeof( char ));
for( i = 0; i < ((height*2) + 1); i++ ){
rowString = *(gameBoard + i);
printf("%s\n",rowString);
}
free(rowString);
}
The game being made is dots and boxes so width and height are the amount of boxes, the arrays are actually allocated as height*2+1 and width*2+1 and is set up to look like this if the height is 2 and width is4, note that the example has all the edges filled in already but normally the edges would just be white spaces:
x-x-x-x-x
| | | | |
x-x-x-x-x
| | | | |
x-x-x-x-x
When I print this the first time it looks like that, but if I try and print it again it looks like this:
x-x-x-x-x
| | | | |
x-x-x-x-x
| | | | |
Any idea on why this is happening?
Before the loop you allocate memory and assign it to the pointer variable rowString. But inside the loop you reassign the variable to point to somewhere else, loosing the original pointer to your allocated memory. Later when you try to free the memory you free the memory in the "2d matrix" instead of the memory you just allocated.
All of this leads to undefined behavior as you then later try to dereference the previously free'd memory (*(gameBoard + i)).
The obvious solution here is to not reassign the pointer, but to copy the string, e.g. with strcpy. Another pretty obvious solution would be to not allocate memory at all, and not even use the rowString variable, as you don't really need it but can use the pointer *(gameBoard + i) directly in your printf call.
Code:
#include <stdio.h>
int main(void)
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int i, j;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 3; j++)
{
printf("%d ", *((*arr+(i*3))+j));
}
printf("\n");
}
return 0;
}
I'm surprised how the above code gives the output:
1 2 3
4 5 6
I know that *(arr+i) == arr[i] and also that I should be using arr[i][j] instead of making everything more complicated, but I don't understand how *((*arr+(i*3))+j) works.
In my understanding, *((*arr+(i*3))+j) can be simplified to *((*arr)+(i*3)+j) since the *(indirection operator) has the most precedence here.
So, when i is zero and j iterates through, 0 to 2, the expression is the same as arr[0][j] which prints the integers of the first subarray.
My confusion builds up when i becomes 1. The next three expressions will be *((*arr)+(1*3)+0), *((*arr)+(1*3)+1) and *((*arr)+(1*3)+2) which can be simplified to arr[0][3], arr[0][4] and arr[0][5].
How does this print the last three values?
int arr[2][3] = {{1,2,3},{4,5,6}};
In memory :
1 | 2 | 3 | 4 | 5 | 6
each number on an adjacent memory "cell" the size of an int, in this order
Second line :
i = 1
j = 0
*((*arr+(i*3))+j)) means *((*arr + 3) + 0)-> *({1, 2, 3} + 3) -> *({4, 5, 6}) = 4
Keep in mind that x[n] is equivalent to *(x + n), whatever x or n. (This also means arr[1] is equivalent to *(arr + 1), *(1 + arr) and so 1[arr] which I find funny)
Here arr[1][0] : x is arr[1] and n is 0 so first equivalence: *(arr[1] + 0)
Second x is arr and n is 1 so *(*(arr + 1) + 0).
Finally arr + 1 means the adress at arr + sizeof(*arr), which means:
(arr + 1) is equivalent to (*arr + 3) because *arr is arr[0] which is of type int[3]
The C language stores multidimensional arrays in what is called row-major order,
so when you declare int arr[2][3] the memory is actually laid out with the entries of the array occurring adjacent to each other in
memory in this sequence:
arr[0][0] arr[0][1] arr[0][2] arr[1][0] arr[1][1] arr[1][2]
This has a couple of consequences that are useful to know:
arr[1] acts like a pointer to a one-dimensional array. just as it does when you declare int **arr;.
The initializers in your initialization list are copied into memory locations in exactly the order you list them.
The array is stored in your memory like :
_____ _____ _____ _____ _____ _____
| 1 | | 2 | | 3 | | 4 | | 5 | | 6 |
----- ----- ----- ----- ----- -----
So even though it is stored in a two dimensional array it is contagiously allocated memory during compilation. When you write a[1][1] the compiler accesses the (1*(no of columns) + 1 ) position from front i.e. the 4 position from start.
See http://www.fredosaurus.com/notes-cpp/arrayptr/23two-dim-array-memory-layout.html
I am trying to print an array however I am not getting the desired output, weird numbers appear after the loop finishes printing the pre-defined array.
Code is:
#include <stdio.h>
int main(){
int intArray[11] = {1,2,8,12,-13,-15,20,99,32767,10,31};
int i=0;
for(i=0;i<sizeof(intArray);i++){
printf("%d\n",intArray[i]);
}
}
Output:
1
2
8
12
-13
-15
20
99
32767
10
31
11
1629976468
2674040
2665720
1627423265
1
2665616
-2147417856
1629976534
1629976468
2674040
0
1627423172
1629976532
0
1629110043
0
0
0
0
0
0
0
0
0
0
0
1629976538
0
1629956432
2674276
0
1627407935
The breaking condition in for loop is wrong! Which causes an index-out-of bound problem as i exceeds the maximum index value that is 10 because array length is just 11. The loop break condition should be < length of array( =11) but not < size of array.
Value of sizeof(intArray) is equals to 11 * sizeof(int) (= 44).
To understand it read: sizeof Operator:
6.5.3.4 The sizeof operator, 1125:
When you apply the sizeof operator to an array type, the result is the total number of bytes in the array.
According to this when sizeof is applied to the name of a static array identifier (not allocated through malloc()/calloc()), the result is the size in bytes of the whole array rather then just address. That is equals to size of each elements multiply by the length of array.
In other words: sizeof(intArray) = 11 * sizeof(int) ( as intArray length is 11 ). So suppose if sizeof(int) is 4-bytes then sizeof(intArray) is equals to 44.
Below a code example and its output will help you to understand further(read comments):
int main(){
int intArray[11] = {1, 2, 8, 12, -13, -15, 20, 99, 32767, 10, 31};
int i = 0;
printf("sizeof(intArray): %d\n",
sizeof(intArray) //1. Total size of array
);
printf("sizeof(intArray[0]): %d\n",
sizeof(intArray[0]) //2. Size of one element
);
printf("length: %d\n",
sizeof(intArray) / sizeof(intArray[0]) //3. Divide Size
);
return 0;
}
Output:
sizeof(intArray): 44 //1. Total size of array: 11 * 4 = 44
sizeof(intArray[0]): 4 //2. Size of one element: 4
length: 11 //3. Divide Size: 44 / 4 = 11
One can check the working code #ideone, note: I am assuming size of int is 4.
Now notice as sizeof(intArray) is 44 that is more then length of array hence the condition is wrong and you have Undefined behavior in the code at runtime. To correct it replace:
for(i=0; i < sizeof(intArray); i++)
// ^--replace-----^
// wrong condition = 44
With:
for(i=0; i < sizeof(intArray) / sizeof(intArray[0]); i++)
// ^------------------------------------^
// condition Corrected = 11
To calculate length of array, I simply divided total size of array by the size of one element and code is:
sizeof(intArray) / sizeof(intArray[0]) // 44 / 4 = 11
^ ^
total size of size of first element
array
sizeof gives you the size of the array in bytes, not elements. To get the number of elements, divide by the size of only one element:
for(i = 0; i < (sizeof intArray / sizeof intArray[0]); i++)
{
printf("%d\n", intArray[i]);
}
It's worth noting that this only works for array types, it doesn't work when you have allocated a block of memory using malloc.
You need to change sizeof(intArray) to
sizeof(intArray)/sizeof(int)
This will give the number of the array elements.
Update
for(i=0;i<sizeof(intArray);i++)
to
for(i=0;i<sizeof(intArray)/sizeof(intArray[0]);i++)
sizeof(intArray) gives total size of array in bytes not number of elements in the array.
You have declared intArray as an array of 11 ints. Each int occupies a certain number of bytes in memory (typically four). So the size of the whole intArray is 11 * 4 = 44 bytes.
When you say i < sizeof(intArray), you are therefore saying i < 44. But your array has only 11 elements, not 44! So your loop will continue past the array bounds. It will continue to read four-byte chunks and interpret them as integers, and print out the garbage values.
That is why all the answers are saying that you need to have your loop condition be
i < sizeof(intArray) / sizeof (intArray[0])
You need to divide the size of the entire array by the size of a single element to get the number of elements in the array. Since you already know the number of elements, you could keep it simpler and just say
i < 11
but for more general cases where you might not know the size of the array, you need to use the other suggested loop condition.
The Motivation
I'm attempting to save various environments via setjmp for the purpose of jumping back to them later and calling functions and making sure that the stack frames run into each other. For Example:
env[0] stack:
----------
| text |
----------
| data |
----------
| |
| |
| |
| |
| |
| |
| |
| ~~~~ |
----------
where the tildes represent the stack frames of main etc.
env[1] stack:
----------
| text |
----------
| data |
----------
| |
| |
| |
| **** |
| **** |
| **** |
| **** |
| ~~~~ |
----------
Where the stars represent a large array I've allocated.
The idea is that if I longjmp to env[0] and start running some methods, then longjmp to env[1] and start running some methods, the stack frames of env[0] will start to fill up the empty space in that array, and the stack frames of env[1] will be on top of that array, and not overwrite the stack frames of env[0]. Basic threading.
I'd also like to have more than just two threads, in fact, I'd like MAXTHREADS. Intuitively it works like this:
for(int i = 0; i < MAXTHREADS; i++) {
char c[STACKSIZE];
if( setjmp(env[i]) != 0 ) {
/* Stuff that thread i will do goes here */
}
}
Test 1
However, as you can clearly see in the following test program, each c array started at the same spot on the stack, defeating the purpose.
for(int i = 0; i < 10; i++) {
char c[10];
printf("On Iteration %d array starts at %x and goes to %x\n",i,c,c+10);
}
Outputs:
On Iteration 0 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 1 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 2 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 3 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 4 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 5 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 6 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 7 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 8 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 9 array starts at ffbfef02 and goes to ffbfef0c
This makes sense for a multitude of reasons, scope dictates that the c array ceases to exist at the end of the loop, additionally the compiler probably moves it outside of the loop because the size is static.
Test 1 gave me the size I want, but not the allocation I want
Test 2
So my next thought was to allocate an array of STACKSIZE * i, so that even though the arrays each started at the same spot, they would be bigger each time and push up my stack pointer far enough when the time came to switch to that environment. Here's the test:
for(int i = 0; i < 10; i++) {
char c[10 * i];
printf("On Iteration %d array starts at %u and goes to %u\n",i,c,c+(10*i));
//note: switched from %x to %u to make comparison mentally simpler
}
However, this outputs
On Iteration 0 array starts at 4290768760 and goes to 4290768760
On Iteration 1 array starts at 4290768744 and goes to 4290768754
On Iteration 2 array starts at 4290768720 and goes to 4290768740
On Iteration 3 array starts at 4290768688 and goes to 4290768718
On Iteration 4 array starts at 4290768648 and goes to 4290768688
On Iteration 5 array starts at 4290768592 and goes to 4290768642
On Iteration 6 array starts at 4290768528 and goes to 4290768588
On Iteration 7 array starts at 4290768456 and goes to 4290768526
On Iteration 8 array starts at 4290768376 and goes to 4290768456
On Iteration 9 array starts at 4290768280 and goes to 4290768370
It's a little hard to see at first, but due to the large numbers, you can focus on only the last three digits.
The first array goes from 760 to 760 -- fine, it's for i = 0
The second array goes from 744 to 754 -- fine, we moved a bit, but it's an array of size 10 in the general position that we want it in
The third array goes from 720 to 740 -- uh-oh, the array didn't start in the same spot as the others, and it's double the size.
To Illustrate the pattern on the stack, each * represents 10 chars in an array, and gaps between chunks of stars are the gaps between the arrays:
*
*
*
*
*
*
~
The tilde is the main,etc as before.
The pattern goes on. This is likely machine dependent, but my machine is allocating the arrays in order, rather than going back down the bottom each time as it did with constant size arrays.
Test 2 gave me the allocation I want, but sizes WAY larger than I'd like.
Test 3
Now having learned that my machine will allocate arrays overwriting each other if they're the same size, but stacked on top of each other if they vary in size, I thought that maybe I could allocate STACKSIZE + i instead of STACKSIZE * i of each. I ran this experiment:
for(int i = 0; i < 10; i++) {
char c[10+i];
printf("On Iteration %d array starts at %u and goes to %u\n",i,c,c+10+i);
}
Which outputs:
On Iteration 0 array starts at 4290768808 and goes to 4290768818
On Iteration 1 array starts at 4290768792 and goes to 4290768803
On Iteration 2 array starts at 4290768776 and goes to 4290768788
On Iteration 3 array starts at 4290768760 and goes to 4290768773
On Iteration 4 array starts at 4290768744 and goes to 4290768758
On Iteration 5 array starts at 4290768728 and goes to 4290768743
On Iteration 6 array starts at 4290768712 and goes to 4290768728
On Iteration 7 array starts at 4290768688 and goes to 4290768705
On Iteration 8 array starts at 4290768664 and goes to 4290768682
On Iteration 9 array starts at 4290768640 and goes to 4290768659
After analysis, it's using the same allocation behavior I expected.
Test 3 gave me the allocation I want, and sizes close to what I want, but still not perfect
The Question
So Test 3's strategy could work in my original code up top, allocate MAXTHREADS arrays of STACKSIZE + i, saving the env between each, but it seems suboptimal. I'm allocating extra space in each array simply to trick my compiler.
Is there a better way to do this? Some other trick to make the compiler allocate fresh arrays of STACKSIZE each time?
How do I get the allocation of tests 2 and 3, with the size of test 1?
You have to do something like this:
jmp_buf states[NUMTHREADS]
char stacks[NUMTHREADS][STACKSIZE];
// your scheduler starts *after* this!
for(;;) {
// setjmp to remember the current thread's state
// longjmp to thread i+1 and use stacks[i+1][top]
}