Seg Fault when accessing an array initialised with malloc - c

Below is a simplified extract of a program I'm writing. I'm having issues accessing elements towards the end of the array.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int n, char *args[n]){
// create 4D array scores[10000][100][100][100] on heap
uint64_t arraySize = 1; // this avoids overflow
arraySize *= 10000;
arraySize *= 100;
arraySize *= 100;
arraySize *= 100;
int (*scores)[10000][100][100] = malloc(arraySize);
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 100; j++) {
printf("%d, %d, %d\n", i, j, scores[i][j][0][0]);
}
}
}
The program loops through the 4D array score and as a test I'm printing the contents of the array. The loop starts off as planned, printing in the format "i, j, 0" for each i and j, until the last success "25, 0, 0".
From this point on I get random numbers rather than 0, starting with "25, 1, 1078528" up until "25, 45, 1241744152" which is then followed by "Segmentation fault (core dumped)".
After fiddling around I found the first non-zero array member to be scores[25][0][7][64].
So I guess I'm running out of space and so am accessing memory I shouldn't be? If anyone knows or has an idea as to how I could fix this I'd really appreciate it.
My PC is running Ubuntu 16.10 64bit, has 16GB RAM and 16GB swap
Edit
After implementing the following suggestions I get a return value of "calloc: Cannot allocate memory".
int (*scores)[100][100][100] = calloc(arraySize, sizeof(int));
if (scores == NULL) {
perror("calloc");
return 1;
}
If I comment out the new if statement (and run the for loop) I get an immediate seg fault. This also happens if I use malloc:
int (*scores)[100][100][100] = malloc(arraySize * sizeof(int));
Why could this be? Surely my system has enough memory
Cheers

Check the return value of malloc() and determine if it failed to allocate.
You forgot to multiply the size of int.
The type of result should be int (*)[100][100][100], not int (*)[10000][100][100].
Using value of buffer allocated via malloc() and not initialized invokes undefined behavior, so don't do that.
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int n, char *args[n]){
// create 4D array scores[10000][100][100][100] on heap
uint64_t arraySize = 1; // this avoids overflow
arraySize *= 10000;
arraySize *= 100;
arraySize *= 100;
arraySize *= 100;
int (*scores)[100][100][100] = calloc(arraySize, sizeof(int));
if (scores == NULL) {
perror("calloc");
return 1;
}
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 100; j++) {
printf("%d, %d, %d\n", i, j, scores[i][j][0][0]);
}
}
}

Your pointer to a variable length array does not use correct array sizes.
The array is: [10000][100][100][100]
but the pointer is: [100][10000][100][100]
And you need to multiply the array size times the size of the object, in this case size of type int.
The pointer definition should be:
int (*scores)[100][100][100] = malloc(arraySize*sizeof(int));
The allocated elements are not initialized. Reading them will yield indeterminate values.
The correct type to store the size of bytes that need to be allocated, is size_t, not uint64_t.
One of the correct ways to allocate the array is:
const size_t bytes = sizeof( int[10000][100][100][100] );
int (*scores)[100][100][100] = malloc( bytes );
(This of course assumes that size_t can represent that value.)

Did you try:
int (*scores)[10000][100][100] = malloc(sizeof(int)*arraySize);
Bye.

Related

C - How would I extract Even numbers from an array and place them into another array called EvenNumbers?

I'm tasked with writing a function that will identify all the even numbers in an sample array {10,2,9,3,1,98,8] and place them in an array called EvenNumbers. I have to allow the function so that it works with different combinations of numbers in the array not just the numbers in the sample array above.
I'm wondering is there any way to add numbers to an array that could be different every time? How would I extract the even numbers an place them into an array? Also
for the even array size its giving me an error that the expression must have a constant value but when I use const int it still gives me that error.
Here is the full question.
"Using the array of sample values {10,2,9,3,1,98,8}, write a function that will identify all the even numbers in an array and place it in an array called EvenNumbers. The function must work in all cases, not just in the case of the array shown. Assume that the array size is always available through a global constant called MAX"
Here is what I have so far. I've no idea how I will extract the even numbers from a for loop and place them in an array. I also dont know what the "expression must have a constant value" is about?
#include <stdio.h>
#include <stdlib.h>
void EvenNumber(int Array[], int size);
int main()
{
int array[7] = { 10,2,9,3,1,98,8 };
EvenNumber(array, 7);
}
void EvenNumber(int Array[], int size)
{
int i;
int EvenArraySize;
for (i = 0; i < size; i++)
{
if (Array[i] % 2 == 0)
{
EvenArraySize++;
}
}
int Even[EvenArraySize];
}
The right way to go is to use malloc to allocate just the right amount of memory.
Count the number of even numbers
Allocate the space needed to store them
Copy even numbers in this space
Do whatever you want with these numbers
Free the allocated space
Snippet:
#include <stdio.h>
#include <stdlib.h>
#define MAX 7
int
main()
{
int array[] = {10,2,9,3,1,98,8};
int *even_numbers;
int i, nb_even_numbers;
for (i = 0, nb_even_numbers = 0; i < MAX; i++)
{
if (array[i] % 2 == 0)
nb_even_numbers++;
}
even_numbers = malloc(sizeof(int) * nb_even_numbers);
if (!even_numbers)
{
perror("malloc");
return 1;
}
for (i = 0, nb_even_numbers = 0; i < MAX; i++)
{
if (array[i] % 2 == 0)
even_numbers[nb_even_numbers++] = array[i];
}
/* do your stuff here */
free(even_numbers);
return 0;
}
First, you can never return a statically declared array from a function (even though you don't explicitly try, your Even array is destroyed when EvenNumber returns) Why? The function stack frame for EvenNumber is released for reuse on return and any locally declared arrays are no longer valid.
You either need to pass a second array as a parameter to EvenNumber, or you can dynamically allocate storage for Even in EvenNumber (with, e.g. malloc or calloc or realloc) and return a pointer to the beginning of the array. (you must also have some way to return the size or use a constant for a max size).
There is no need to use % (modulo) to test whether a number is odd/even. All you need to do is look at bit-0 (little endian). If it is 0, then the number is odd, if it is 1, then its even. Much more efficient than calling modulo which incorporates division.
Finally, main is type int and therefore returns a value.
Putting those pieces together, you can do something simple like the following:
#include <stdio.h>
#include <stdlib.h>
void EvenNumber (int *array, int *even, int size, int *esize);
int main (void)
{
int array[] = { 10,2,9,3,1,98,8 },
i, n = sizeof array / sizeof *array,
even[n], /* a VLA of the same size as array is fine here */
esize = 0;
EvenNumber (array, even, n, &esize);
printf ("array: ");
for (i = 0; i < n; i++)
printf (" %2d", array[i]);
printf ("\neven : ");
for (i = 0; i < esize; i++)
printf (" %2d", even[i]);
putchar ('\n');
return 0;
}
void EvenNumber (int *array, int *even, int size, int *esize)
{
int i;
for (i = 0; i < size; i++)
if ((array[i] & 1) == 0) /* simply looking at bit-0 is all you need */
even[(*esize)++] = array[i];
}
Note: esize is passed as a pointer to EvenNumber and updated within the function so that the number of elements in even are available back in the calling function (main() here).
Example Use/Output
$ ./bin/arrayeven
array: 10 2 9 3 1 98 8
even : 10 2 98 8
Let me know if you have any further questions.

Strange behavior while filling dinamically allocated 2D char array in C

I need to create a program that plays the game Hex on a 14x14 board.
So I created, allocated and filled the board with '-' (our pattern for empty spaces).
When I try to print the board's coordinates, I don't always get '-' but some random characters.
Also, if I try to printf array[i][j] on the createBoard function after the line "board[i][j] = '-';" I get a segmentation fault right after it prints tab[8][0].
What is causing this and how can I fix it?
My code:
#include <stdio.h>
#include <stdlib.h>
char **createBoard()
{
/*Allocates a 14x14 matrix and fills it
*with '-' to create the board.*/
int i, j;
char **board;
board = malloc(14);
if (!board) exit(1);
for (i = 0; i < 14; i++){
board[i] = malloc(14);
if (!board[i]) exit (1);
for (j = 0; j < 14; j++)
board[i][j] = '-';
}
return board;
}
int main()
{
int i, j;
char **board = createBoard();
for (i = 0; i < 14; i++)
for (j = 0; j < 14; j++)
printf("tab[%d][%d]: %c\n",i, j, board[i][j]);
return 0;
}
For starters it is not clear why you don't want to declare an array instead of allocating dynamically numerous one-dimensional arrays.
As for the code then this memory allocation
board = malloc(14);
is invalid. You have to write
board = malloc( 14 * sizeof( char * ));
Also you should free all the allocated memory in the reverse order relative to its allocation before the program ends.
Take into account that it is always better to use named constants instead of magic numbers. At least you could write either
#define N 14
before main
or
const int N = 14.
and use the variable N everywhere where you are using magic number 14.
By the way according to the C Standard function main without parameters shall be declared like
int main( void )
The variable *board is a pointer, but you only allocate one byte for each array element, which should be
#define DIM 14
board = malloc(DIM * sizeof *board);
Following that up with the second allocation
board[i] = malloc(DIM * sizeof **board);
This also allows (a) that the dimension 14 is hard coded in only one place in the program and (b) the allocation will survive if you later make the board's element a different type, for example a struct, as the program develops.

How to realloc based on size of array?

Say you malloc enough memory space to hold an array of size 20. The program is running and now I need enough memory for an array of size say 40. I tried to do this using realloc but it doesn't seem to be working. My code is the following(I'm trying to find the sum of all even-valued fibonacci terms below 4million):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv){
int i,sum,size;
int *fibo;
size = 20; //initial size of array
fibo = (int *) malloc(size*sizeof(int));
fibo[0]=1;
fibo[1]=1;
i=2;
sum=0;
while(fibo[i-1]<4000000){
fibo[i] = fibo[i-1]+fibo[i-2];
printf("fibo[%d] = %d\n", i, fibo[i]);
if(fibo[i]%2 == 0){
sum+= fibo[i];
}
i++;
if(i>size){
fibo = (int *) realloc(fibo, (size *= 2)*sizeof(int));
}
}
printf("Sum = %d\n", sum);
return 0;
}
Anyone know why realloc is failing, and how I can fix it?
During the last iteration, i equals 20 but the expression
if(i>size)
is false, so you do not actually use realloc, then by writing to
fibo[20]
the program is accessing part of the memory that does not belong to it. Changing the expression to
if(i>=size)
should fix it :)

C: Dynamic memory allocation using pointer to array with fixed number of chars

so I guess this is more a stylistic question.
I need to write into a dynamic array of elements with the size of 3 bytes. (bitmap with pixel size of 24bpp)
So, every element would have to be a char[3].
If I want to avoid using a struct pixel{ char R, char G, char B}, to avoid the usage of preprocessor statements, is it possible to write it as
char* pixel[3]
and allocate in steps of 3*sizeof(char)?
To account for height and width, I would need a char** pixel[3], and having to allocate in single char steps would make that a char*** pixel.
So I guess I'm looking for a way to avoid using a pointer-pointer-pointer.
Thanks!
Do you mean N blocks of 3 unsigned char' s [0...255]?
Note the difference:
unsigned char *pixel[3] -> array of pointers to char
Vs
unsigned char (*pixel)[3] -> pointer to array of chars
#include <stdio.h>
#include <stdlib.h>
#define N 4
int main(void)
{
unsigned char (*pixel)[3];
pixel = malloc(sizeof(*pixel) * N);
pixel[0][0] = 0;
pixel[0][1] = 128;
pixel[0][2] = 255;
/* ... */
pixel[3][0] = 0;
pixel[3][1] = 128;
pixel[3][2] = 255;
printf("R:%d G:%d B:%d\n", pixel[0][0], pixel[0][1], pixel[0][2]);
free(pixel);
return 0;
}
If you don't know N before hand replace malloc with realloc
You can simulate this using a 1D array. Say you want to allocate a wxh rectangle of pixels. You could write.
char *pixels = (char *) malloc(w*h*3*sizeof(char));
Now the 3 color bytes appear contiguous in memory and you can access any cell using some arithmetic
You can get/set the color channels at cell (i,j) by defining the macros:
#define r(p, i, j) ((p)[(3*((w)*(i)+(j)))])
#define g(p, i, j) ((p)[(3*((w)*(i)+(j)) + 1)])
#define b(p, i, j) ((p)[(3*((w)*(i)+(j)) + 2)])
Call looks like r(pixels, 0, 1).
If you don't want structs, you can't avoid writing char***.
But you can use a type, to make it more stylish.
So the best solution matching your requirements seems to be:
#include <stdlib.h>
typedef char*** pixelmap_t;
int main() {
int channels = 3, width = 10, height = 10;
pixelmap_t test = malloc(width*height*channels);
int x = 1, y = 2, channel = 0;
test[x][y][channel] = 3;
free(test);
return 0;
}
It seems, I totally fucked up. I confused the following two things:
When you declare a static 3D-Array pixels[100][100][3], then the type is not char***. It is a one-dimensional array of 300 consecutive items in memory.
When you declare a char*** and assign 300 items in memory, then dereferencing all of the dimensions with the pixels[x][y][z] syntax results in derefrencing the first dimension and interpreting the value in memory as pointer and derefrencing this pointer instead of computing the correct offset in a 3D-Array.
That means, I overlooked, that the array[x][y][z] accessor syntax has two different semantics. The first I would call the array ([x][y][z]) semantic for 3D-arrays and the second I would call the ((array[x])[y])[z] semantics for char*** (I used the brackets for emphasizing).
This code snipped compiles and works (tested it) - but does not use heap memory.
For heap memory I don't know an other solution than those, which have been posted already (malloc(width*height*channels) and access with pixels[c + channels*(y + x*height)]).
#include <stdlib.h>
#include <stdio.h>
int main() {
int channels = 3, width = 10, height = 10;
char test[width][height][channels];
char *ptr = (char*) test;
for (int i = 0 ; i < channels * width * height ; i++) {
ptr[i] = (char) (i % 255);
}
for (int x = 0 ; x < width ; x++) {
for (int y = 0 ; y < height ; y++) {
for (int c = 0 ; c < channels ; c++) {
int d = (int) test[x][y][c];
printf("%d %d - %d : %d\n", x, y, c, d);
}
}
}
return 0;
}

professional array-handling

I am an unexperienced C-programmer: I want all the numbers below 5000 that are multiples of 5. Here is how I do this currently:
int main()
{
int i;
const int max =5000-1;
for(i=2; i<(max+1); i++)
{
if(!(i%5))
{
printf("%d\n", i);
}
}
return 0;
}
Say that I want them all listed in an array. What I could do is just to pre-allocate an integer array and fill out the various position. Naturally I can't know the exact required length beforehand, so I would over estimate it length.
However, I come from a C++ background, so normally what I would do there is to pushback a vector, all clean and tidy. But what is the professional way to do this in C? Would you guys pre-allocate or dynamically resize the array?
I am currently using Herbert Schildt's "Turbo C/C++", I'm sure there are much better (and up-to-date) references out there when I get more into things.
realloc does everything you're talking about. Allocating an array, growing an array, shrinking an array: it does it all.
int max = 5000; /* why subtract one if you have to add one to use it? */
int *arr = NULL;
int i;
arr = realloc(arr, max * sizeof *arr); /* allocate generous array */
for (i = 0; i < max; i++) {
/* ... */
}
max = 10000;
arr = realloc(arr, max * sizeof *arr); /* grow array */
max = 100;
arr = realloc(arr, max * sizeof *arr); /* shrink array */
Now there is some popular advice that you should always save the return value from realloc as a separate variable and check it for NULL before overwriting your real pointer variable. This is because there are bizarre situations where the realloc may fail, even on something as innocuous as shrinking an array. This can happen if the malloc subsystem is implemented using fixed-sized buckets, among other possibilities. A shrinking request may fail with a fixed-sized bucket system if there simply aren't any more "small" regions available.
If realloc fails, it returns NULL, but the original allocation is left intact. If you just write the return value into your pointer variable, that data will lost. So, in general, you should try to do this instead:
int *tmp;
tmp = realloc(arr, max * sizeof *arr);
if (tmp) {
arr = tmp;
} else {
/* maybe issue an error message? */
}
If you want to allocate the perfect size, you could try this :
#include <stdio.h>
#include <stdlib.h>
int main(){
int i, j;
int max = 5000;
int * ourNumbers = 0;
int count = 0;
for(i = 2; i < max; i++){
if (i % 5 == 0){
count += 1;
}
}
printf("\ncount = %d\n", count);
ourNumbers = (int *) malloc(sizeof (int) * count);
// and after you can populate your array with those values;
// like this you will allocate the exact memory
}
I know that is not so efficient, but I hope it will help you :)

Resources