C Array Allocation in a Loop For Threading - c

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]
}

Related

function to zero array elements

I wrote this code that check suduko answers and for some reason my the array which I sum the squares of the suduko into is all zeros in the functions I zero it in, but when I use it in my check function it isn't all zeros
if i move the exact same code of my array zeroing function to my other function and run it it works.
(i am using c99, dont know if it matters)
Any ideas?
int squareSum[5][5];
//set array elements to zero
setArrayToZero(squareSize, squareSize, squareSum);
/*for(int i = 0; i<squareSize; i++){
for(int j = 0; j<squareSize; j++)
squareSum[i][j] = 0;
}*/
printf("%d, %d\n%d, %d\n\n", squareSum[0][0], squareSum[0][1], squareSum[1][0], squareSum[1][1]);
this is the array is case squareSize is two
if i add the for in the comments in, the array isall zeros, and as you can see below its the exact same as the function i call.
void setArrayToZero(int rows, int columns, int array[][columns]){
for(int i = 0; i<rows; i++)
for(int j = 0; j<columns; j++)
array[i][j] = 0;\\if i print the array in function its all zeros.
p.s
i know i am using only part of the array, its an assignment from the university and we are not allowed to use malloc so i am creating the array at thier max size - 25.
thank you in advance.
full c file:
https://drive.google.com/open?id=1L00L3lvMYNcaz2SswEBnmi9KO-79oaHg
all the print functions, are part of the demand for the course (for auto checking)
A reference to an object of type array-of-T which appears in an
expression decays (with three exceptions) into a pointer to its first
element; the type of the resultant pointer is pointer-to-T.
So that means in this case also (this is not one of those 3 exceptions) your passed array will decay into pointers and now you change to the array by accessing the address, that's why it will be retained in the callee function.
You are doing it the right way. The problem is not with passing or anything. Maybe you are accessing it wrong or maybe you didn't initialize it properly. But there is nothing wrong with the zeroing out.
And for further information everything is pass by value in C. There is nothing called pass by reference in C. The pointer workings makes us think that there is something called pass by reference in C but that's not the case, here also pointer variables are copied into some local variable in the called function. but as we have those addresses in the called function and we access them and make changes - they retain in callee function.
After OP posted the sample code
Apaprt from the overly complicated sudoku checking logic there is much more going wrong.
I will just mention the printing part.
In C elements of 2d-arrays are stored sequentially. When we pass the 2d array to the function we need to specify the column size so that we can determine the correct element.
Suppose you want to access a[4][7] in 10x13 array. The element would be at the address &a[0][0]+4*13+7. That's why the column part is passed as an argument.
Now what you did :
int squareSum[5][5], rowColSum[25][2];
//set arrays elements to zero
setArrayToZero(size, 2, rowColSum);
setArrayToZero(squareSize, squareSize, squareSum);
The first one is alright. As there are 2 columns. But what about the second one?
here you are telling the function that you are passing an array with column size = 2 but that is not the case. It is still the 2d array with 5 columns.
That's where you had the problem. Suppose you initialize the array with 10,21,34,14
Suppose grid is 5x5 array (in your case it's 25x25)
grid[5][5] array
And you do this
for(int i = 0; i<squareSize; i++)
for(int j = 0; j<squareSize; j++)
scanf("%d",&grid[i][j]);
/*
Input is 13 17 19 23
*/
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
/ \ \ / \ \
13 17 19 23
Now you access it like this
You pass it to the function with this call print2dArray(int row, int col, int g[][col])
You call like this `print2dArray(2,2,grid);``
...
for(int i = 0; i<row; i++)
for(int j = 0; j<col; j++)
printf("%d",&grid[i][j]);
Now you will print these elements (i) : denotes the order
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
/ \ \ ^ ^ / \ \
13 17 | | 19 23
(1) (2) (3) (4)
Similarly, those were uninitialized in your case. That's why you got those weird results. You were initializing some elements of the 2d array to 0 but when you are reading the array then you were accessing some different elements. That's why the wrong result.
Solution for this:
Call int correctSum = inputGrid(squareSize, 25, grid); Note that it should be squareSize. Accordingly change the storage of digitsCounter in inputGrid.
The function signature for inputGrid would be inputGrid(size, col, grid[][col]);
Same when calling the
setArrayToZero(size, 2, rowColSum); and
setArrayToZero(squareSize, 5, squareSum);
I simply didn't check the logic. The answer deals with explaining the printing behavior of the 2d array.

How should you add elements to a multi dimensional array? (In C)

I'm working on a table football cup program (in C), where I have 16 people facing off to get to the final. I'm having trouble putting elements into the different elements of the array (which has sort of stopped my progress until I figure it out). I've searched on the internet (not extensively) about pointers, but I can't find anything on multi dimensional arrays.
I have 8 games, each with 2 participants, who each play 5 matches against each other. Hopefully that means I define the array as int lastSixteen[8][2][5]. All participants have a unique ID
Assuming I have declared my arrays correctly... On to the main question.
This is what I'm currently doing:
int i;
for(i=0; i<MAX_PLAYERS/2;i++){
roundOne[i] = i;
}
I want to set the first dimension of my array to be the numbers 1 through 8 incl. but I run into 'error: incompatible types in assignment'.
I tried setting the line with the assignment to be roundOne[i][][] = i; but as I expected, that didn't work either.
Later on in the program I need to set the second set of numbers to be the games participants to be the 16 participants (to keep it simple I'm doing it in ascending numerical order) so Game 1 is Player 1 and Player 2, Game 2 is Player 3 and 4 etc.
for(i=0; i<16; i++){
if(i % 2 != 0){
roundOne[(MAX_PLAYERS/2)-1][0] = i; /* puts 1,3,5,7,9,11,13,15 */
}
else{
roundOne[(MAX_PLAYERS/2)-1][1] = i; /* puts 2,4,6,8,10,12,14,16 */
}
}
I'm assuming the second part will be fixed by the answer to the first part since they return the same error, but I included it because I don't know.
A sample of code that has a minimal, Complete, and Verifiable example.
#include <stdio.h>
#define MAX_PLAYERS 16
int main(void){
int i;
int roundOne[8][2][5];
/* seeded in numerical order.*/
for(i=0; i<MAX_PLAYERS/2;i++){
roundOne[i] = i;
}
for(i=0; i<MAX_PLAYERS; i++){
if(i % 2 != 0){
roundOne[(MAX_PLAYERS/2)-1][0] = i;
}
else{
roundOne[(MAX_PLAYERS/2)-1][1] = i;
}
}
return 0;
}
Thanks in Advance,
Rinslep
You can't just use a multi dimensional array - it doesn't do what you want. And here is why: Lets say you have 8 games and 2 players (forget that there are 5 matches for a second) That means your multi dimensional array would have 16 spots:
Player
0 1
+---+---+
0 | | |
+---+---+
1 | | |
+---+---+
2 | | |
G +---+---+
a 3 | | |
m +---+---+
e 4 | | |
+---+---+
5 | | |
+---+---+
6 | | |
+---+---+
7 | | |
+---+---+
Now you want to put the game number in there AND you want to put the unique player IDs in there AND you might want to put other stuff in there (like who won and the score)? How are you going to do that? There are a couple choices:
The game number is the index into the array - not a value you store in the array. Now you can store the palyer IDs for each game in the array. But this still doesn't address storing other stuff (like who won and the score)
If the game number needs to be stored in the array (or other things like who won and the score) you will need to store more than one thing in the array so the array cannot hold ints - you need an array of structures.
It is hard to guess what the right data structure is because it depends on what your program is going to do, but I think I would do this:
typedef struct match
{
int score[2]; /* index 0 is player 1, index 1 is player 2 */
int winner; /* index into the player and score arrays (either 0 or 1) */
};
typedef struct game
{
int players[2]; /* index 0 is player 1, index 1 is player 2 */
match matches[5];
};
game games[8];
Now, the the game number (1-8) is just the index to games plus 1, the match number (1-5) is just the index to matches plus 1 and if you want to make unique player numbers that go from 1-16 you can do this:
i=1;
for(int g=0;g<8;g++)
for(int p=0;p<1;p++)
games[g].player[p]=i++;
You need to initialize the array with dynamic allocation.
How do I work with dynamic multi-dimensional arrays in C?
Think of it this way
A = [
[B],
[C],
[D],
...
]
So lets say we need an array round with 10 rows and each row has 20 columns. They will all be filled with integer values.
Option One - Dynamically Allocating
Define the number of buckets the array will have. We are taking the size of the pointer because each bucket will container a pointer/array that represents the inner array.
int** round;
round = malloc(10 * sizeof(int*))
Now that we have allocated the space for the buckets, go through and give space for the points. This one is just a normal integer so we take the sizeof(int).
for (int i = 0; i < 10; i++) {
round[i] = malloc(20* sizeof(int))
}
Option Two
We can define the size of the multidimensional array in a bit of an easier way. We know the number of rows and the number of columns. So alternatively we can allocate the space like this:
int* round;
round = malloc (10 * 20 * sizeof(int));
Both of these will produce the array round[10][20] with memory allocated for it. With C you can't add elements to an array on the fly if the size of the array is unknown, in my experience linked lists are better for this.
Edit: I see that you updated the question, this code can be used with a 3D array also. You can easily use option two as 3D like round = malloc(x * y * z * sizeof(int)), where x, y, and z are equal to the dimensional values. You can also modify option one to work with this also.

C - how are dynamic arrays printed?

I'm a bit baffled with whether I'm printing my dynamic array correctly. I'm parsing an input file. Say the input file is:
x 6 9 15,
then my goal is to store 1, 2 and 3 into an array called x. It's doing exactly this. I've set the size of the array using:
arr = malloc(sizeof(int)*noValues);
(I also have int *arr declared as a global variable in my file)
where noValues is equal to the number of values encountered in the input file (in this case 3).
I then print the array using:
for (i = 0; i < noValues; i++) {
printf("arr[%d]: %d\n", j, arr[j]);
}
and get the following output:
arr[0]: 6
arr[1]: 9
arr[2]: 15
However, when I change the "noValues" in the for loop to 10, I get the following:
and get the output:
arr[0]: 6
arr[1]: 9
arr[2]: 15
arr[3]: 0
arr[4]: 0
arr[5]: 0
arr[6]: 49
arr[7]: 0
arr[8]: 17060496
arr[9]: 0
Why am I getting some non 0 values? Shouldn't they all be 0? Any clear-up would be appreciated. Is this normal C behaviour?
You are accessing "elements" out of the boundary of arr, this is undefined-behavior; that's why you get values that are seemingly random (but the application could just as well crash).
You're accessing past the end of the array, which is undefined behavior. Technically anything can happen when you do that, but there are two things that typically happen in practice: either the program will crash, or you'll just get the value of whatever bytes are located in memory past the end of the array. (But this isn't something that you can, or should, rely on.)
The uninitialized array behavior is not fix. The value of uninitialized array is zero ,garbage possible. if you want to get value zero of all the elements in the array then use bzero or memset function.

c beginner, vectors

I'm a c beginner and i've a problem (as usual). I wrote this simple program:
#include <stdio.h>
#define SIZE 10
main()
{
int vettore[9];
int contatore1,contatore2;
for(contatore1 = 0; contatore1 <= 9; ++contatore1)
{
vettore[contatore1] = contatore1*2;
}
printf("%d\n\n", vettore[9]);
for(contatore2 = 0; contatore2 < 10; ++contatore2)
{
printf("%d\n", vettore[contatore2]);
}
printf("\n%d\n", vettore[9]);
return 0;
}
The output of this program is:
18
0
2
4
6
8
10
12
14
16
9
10
Why the value of vettore[9] changes 3 times? And why it has the correct value only on the first line of the output? thank you :)
C arrays are zero based so valid indexes for a 9 element array are [0..8]. You are writing beyond the end of your array. This has undefined results but is likely corrupting the next stack variable.
In more detail... vettore has 9 elements, which can be accessed using vettore[0] ... vettore[8]. The final iteration of your first loop writes to vettore[9]. This accesses memory beyond the end of your array. This results in undefined behaviour (i.e. the C standard does not specify expected outcome here) but it is likely that the address of vettore[9] is the same as the address of contatore2, meaning that the latter variable is written to.
You have a similar problem in the next loop which prints more elements than vettore contains.
You can fix this by changing your loops to
for(contatore1 = 0; contatore1 < 9; ++contatore1)
for(contatore2 = 0; contatore2 < 9; ++contatore2)
Note that it would be safer if you changed to calculating the size of the array instead, by using sizeof(vettore)/sizeof(vettore[0]) in the exit test of your loops in place of hard-coding 9.
Your array vettore has 9 elements, but by referencing vettore[9], you're actually referencing the 10th element (since element indexing starts from 0). So it's some random location on the stack, without a well-defined value.
The solution is to index only up to vettore[8], or define vettore to have size 10.
check this out:
for(contatore2 = 0; contatore2 < 10; ++contatore2)
{
printf("%d\n", vettore[contatore2]);
}
you are displaying 11 elements of the vettore array (which is defined as a 9 ints array). I think that the error is in the random allocation on the stack
the vettore size as you defined is 9
int vettore[9];
and in your loop you start from 0 till 9 so you are playing with 10 elements of the array and not 9 (size of the array)
you should define the array with size 10
int vettore[10];
Arrays (i.e. "vectors") start at index zero NOT one; it's contents may be, for example, 5 but it will occupy index locations of 0,1,2,3,4....
[1][2][3][4][5] <- Five items
0 1 2 3 4 <- Their respective locations in the array
Same goes for visualizing characters in strings.....(technically the location in memory contains ASCII value-- look into that for fun ;) )
['c']['a']['t'] <- Three items
0 1 2 <- Their index location in the array
I suggest Kochan's C Programming book; great for starting out!!!

Assigning a value to a variable gets stored in the wrong spot?

I'm relatively new to C, and this is baffling me right now. It's part of a much larger program, but I've written this little program to depict the problem I'm having.
#include <stdio.h>
int main()
{
signed int tcodes[3][1];
tcodes[0][0] = 0;
tcodes[0][1] = 1000;
tcodes[1][0] = 1000;
tcodes[1][1] = 0;
tcodes[2][0] = 0;
tcodes[2][1] = 1000;
tcodes[3][0] = 1000;
tcodes[3][1] = 0;
int x, y, c;
for(c = 0; c <= 3; c++)
{
printf("%d %d %d\r\n", c, tcodes[c][0], tcodes[c][1]);
x = 20;
y = 30;
}
}
I'd expect this program to output:
0 0 1000
1 1000 0
2 0 1000
3 1000 0
But instead, I get:
0 0 1000
1 1000 0
2 0 20
3 20 30
It does this for any number assigned to x and y. For some reason x and y are overriding parts of the array in memory.
Can someone explain what's going on?
Thanks!
tcodes[3][0] = 1000;
tcodes[3][1] = 0;
are writing off the end of your array twice. [3] allocates slot ids 0-2 and [1] only allocates 1 actual slot [0].
Change your initialization of tcodes to signed int tcodes[4][2]; for 4 entries by 2 entries.
The other answers are right, but to help explain what's actually happening:
You have the following local declarations:
signed int tcodes[3][1];
int x, y, c;
Those get stored right next to each other in the stack frame in memory:
tcodes
x
y
z
tcodes has 3 spots, and trying to write to tcodes[n] just means to find where tcodes points to in memory and move over to the nth spot (I'm going to ignore your second dimension since it was just 1 anyway). If you try to write to spot 3, it's going to move over 3 spots from the beginning of tcodes, even though tcodes isn't that big. Since x is located right after tcodes, in the spot tcodes[3] would be in, that memory gets overwritten and the value of x changes. tcodes[4] would overwrite y, and tcodes[5] would overwrite z. If you kept making n bigger (or negative, which is legal), you could overwrite anything you're allowed to access in memory, which can screw up your program in bad and hard-to-find ways
Change it to this:
signed int tcodes[4][2];
If You define an array like this:
int somearr[3];
You get an array that has 3 elements. Indexes start form 0, so those elements are:
somearr[0]
somearr[1]
somearr[2]
Arrays and other variables defined inside a function, like in Your code, are allocated on the stack. It just so happens, that variables x and y are placed on the stack next to Your array. If you try to access elements
tcodes[3][0] or tcodes[3][1]
You access a part of a stack, that is behind Your array and, as Your output show, it's the spot, where variables x and y are placed.
In fact definition like this
signed int tcodes[3][1];
creates an array containing 3 elements, each of which is an array too - an array containing one signed int. When You write tcodes[1][1], You are accessing non-existing "second" element of your second array. The place in memory, that the compiler accesses when it interprets tcodes[1][1] overlaps with tcodes[2][0];
As you are writing beyond the array boundaries, you are writing on the memory allocated to x and y variables on stack. In this case, they happen to be same as tcodes[3][0] == x and tcodes[3][1] == y as the addresses are same.
If you are doing it in a called function and the array is passed by reference, you might end up in stack corruption.
The bottom line is that in C, arrays are 0 based.
You need to pay attention to the solution given by Robin Oster above. The other folks may be giving you "too much information". Just count the number of items in each dimension better, don't forget the zero'th item counts!

Resources