Getting segmentation faults when flipping image - c

When I'm running this code, I keep getting segmentation faults. I know segmentation faults occur when there's not enough memory allocated to the array. Does anybody know where the seg fault is occuring at?
void flip_horizontal( uint8_t array[],
unsigned int cols,
unsigned int rows )
{
for(int r = 0; r < rows; r++)
{
unsigned int left = 0;
unsigned int right = cols;
int* array = malloc(sizeof(uint8_t));
assert(array);
while(left != right && right > left)
{
int temp = array[r * cols+ left];
array[(r * cols) + left] = array[(r * cols) + cols - right];
array[(r * cols) + cols - right] = temp;
right++;
left++;
}
free(array);
}
}

You made a very simple error. Your left and right indices should be moving towards each other; instead, you're incrementing both of them inside your loop.

int* array = malloc(sizeof(uint8_t));
......
free(array);
You allocated memories, assigned its address to 'array' and the size of memory is only 1 byte. There is only 1 byte while 'cols' may be greater than 1, the size of memory is not large enough. Remove those 2 lines can fix the first issue. BTW, the variable 'array' should not be changed and you don't need a buffer to flip.
Besides, the left, right and swapping loop should be:
unsigned int left = 0;
unsigned int right = cols - 1;
while(left < right) {
int temp = array[r * cols + left];
array[r * cols + left] = array[r * cols + right];
array[r * cols + right] = temp;
right--;
left++;
}

Related

Free array returned from function

apologies if this has appeared elsewhere, I've not been able to find a clear answer.
I've been using Ed S's answer, Option 1 (linked below) to allocate memory, populate the array, then return it back to the caller.
He recommends freeing the memory after you've finished with it, however when I added the free() line, I get a core dump.
I've had a poke around with GDB, but my skills probably aren't what the need to be.
Thanks in advance for any help you can give.
Link to answer: Returning an array using C
Code:
#include <stdio.h>
#include <stdlib.h>
char * createArray();
int main(int argc, char *argv[]){
printf("Creating Array...\n");
// pointer to an int
char *p;
// size of the array
int i,j;
// width of array
int width = 7;
// height of array
int height = 5;
// get an array from the function
p = createArray(width, height);
// check if p was created properly
if (p){
// print out the array
for (i = 0; i < width; ++i){
for (j = 0; j < height; ++j){
printf("[%c] ", *(p + (i * width) + j));
}
printf("\n");
}
// here's where it hits the fan
free(p);
}
return 0;
}
char * createArray(int w, int h){
// allocate some memory for the array
char *r = malloc(w * h * sizeof(char));
// check if the memory allocation was successful
if(!r){
return NULL;
}
int i, j;
int count = 0;
for (i = 0; i < w; ++i){
for (j = 0; j < h; ++j){
*(r + (i * w) + j) = 'X';
++count;
}
}
return r;
}
With this
char *r = malloc(w * h * sizeof(char));
You allocate w * h (7 * 5 = 35 bytes) of memory. But
*(r + (i * w) + j) = 'X';
can access well beyond the 35 bytes you have allocated (you'll see if you test the possible values for i * w + j in the loop), resulting in undefined behaviour.
This possibly overwrites the malloc's internal data structures and thus you happen to get core dump when you free().
You made a mistake on these lines
*(r + (i * w) + j) = 'X';
and
printf("[%c] ", *(p + (i * width) + j));
To keep inside the boundaries of your "2D" array -it's one dimensional but you are working around it like a compiler would-it should be i * length in there:
*(r + (i * h) + j) = 'X';`
and
printf("[%c] ", *(p + (i * height) + j)); `
If you use this, you should be able to stay within the boundaries without making a mess.

How can I concatenate two arrays in C using memcpy?

I have 2 arrays with coordinates and i want to copy them into one array. I used 2 for loops and its working, but i want to know, if i could do it without them, i dont know how to use memcpy in this situation. Here is my code:
int *join(int *first, int *second,int num, int size) {
int *path= NULL;
int i = 0 , j = 0;
path = (int*) malloc (2*size*sizeof(int));
for(i = 0 ; i < num; i++) {
path[i * 2] = first[i * 2];
path[i * 2 + 1] = first[i * 2 + 1];
}
for(i = num; i < size ; i++) {
path[(i*2)] = second[(j+1)*2];
path[(i*2)+1] = second[(j+1)*2 +1];
j++;
}
return path;
}
Just calculate the correct number of bytes to copy and copy from each origin to the correct offset:
int *join(int *first, int *second, int num, int size) {
// Compute bytes of first
const size_t sizeof_first = sizeof(*first) * 2U * num;
// Computes bytes of second as total size minus bytes of first
const size_t sizeof_second = sizeof(int) * 2U * size - sizeof_first;
int *path = malloc(sizeof(int) * 2U * size);
// Copy bytes of first
memcpy(path, first, sizeof_first);
// Copy bytes of second immediately following bytes of first
memcpy(&path[2U * num], second, sizeof_second);
return path;
}

Flipping images from left to right and from top to bottom

I made two functions where one flips the image from left to right and the other one flips the image from top to bottom. But for some reason, when I load the image, nothing happened to the images.
This is the code for flipping from left to right.
void flip_horizontal( uint8_t array[],
unsigned int cols,
unsigned int rows )
{
unsigned int left = 0;
unsigned int right = cols;
for(int r = 0; r < rows; r++)
{
while(left != right && right > left)
{
int temp = array[r * cols+ left];
array[(r * cols) + left] = array[(r * cols) + cols - right];
array[(r * cols) + cols - right] = temp;
right++;
left++;
}
}
}
And this is the code for flipping from top to bottom.
void flip_vertical( uint8_t array[],
unsigned int cols,
unsigned int rows )
{
unsigned int top = 0;
unsigned int bottom = rows;
for(int r = 0; r < cols; r++)
{
while(top != bottom && bottom > top)
{
int temp = array[r * rows+ top];
array[(r * rows) + top] = array[(r * rows) + rows - bottom];
array[(r * rows) + rows - bottom] = temp;
bottom++;
top++;
}
}
}
Try moving these inside your for loop:
unsigned int left = 0;
unsigned int right = cols;
unsigned int top = 0;
unsigned int bottom = rows;
Otherwise, you will only flip the first row/column.
There are some other issues in the way you're indexing as well but I won't spoil the fun of fixing those :-)

How do we allocate a 2-D array using One malloc statement

I have been asked in an interview how do i allocate a 2-D array and below was my solution to it.
#include <stdlib.h>
int **array;
array = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
{
array[i] = malloc(ncolumns * sizeof(int));
if(array[i] == NULL)
{
fprintf(stderr, "out of memory\n");
exit or return
}
}
I thought I had done a good job but then he asked me to do it using one malloc() statement not two. I don't have any idea how to achieve it.
Can anyone suggest me some idea to do it in single malloc()?
Just compute the total amount of memory needed for both nrows row-pointers, and the actual data, add it all up, and do a single call:
int **array = malloc(nrows * sizeof *array + (nrows * (ncolumns * sizeof **array));
If you think this looks too complex, you can split it up and make it a bit self-documenting by naming the different terms of the size expression:
int **array; /* Declare this first so we can use it with sizeof. */
const size_t row_pointers_bytes = nrows * sizeof *array;
const size_t row_elements_bytes = ncolumns * sizeof **array;
array = malloc(row_pointers_bytes + nrows * row_elements_bytes);
You then need to go through and initialize the row pointers so that each row's pointer points at the first element for that particular row:
size_t i;
int * const data = array + nrows;
for(i = 0; i < nrows; i++)
array[i] = data + i * ncolumns;
Note that the resulting structure is subtly different from what you get if you do e.g. int array[nrows][ncolumns], because we have explicit row pointers, meaning that for an array allocated like this, there's no real requirement that all rows have the same number of columns.
It also means that an access like array[2][3] does something distinct from a similar-looking access into an actual 2d array. In this case, the innermost access happens first, and array[2] reads out a pointer from the 3rd element in array. That pointer is then treatet as the base of a (column) array, into which we index to get the fourth element.
In contrast, for something like
int array2[4][3];
which is a "packed" proper 2d array taking up just 12 integers' worth of space, an access like array[3][2] simply breaks down to adding an offset to the base address to get at the element.
int **array = malloc (nrows * sizeof(int *) + (nrows * (ncolumns * sizeof(int)));
This works because in C, arrays are just all the elements one after another as a bunch of bytes. There is no metadata or anything. malloc() does not know whether it is allocating for use as chars, ints or lines in an array.
Then, you have to initialize:
int *offs = &array[nrows]; /* same as int *offs = array + nrows; */
for (i = 0; i < nrows; i++, offs += ncolumns) {
array[i] = offs;
}
Here's another approach.
If you know the number of columns at compile time, you can do something like this:
#define COLS ... // integer value > 0
...
size_t rows;
int (*arr)[COLS];
... // get number of rows
arr = malloc(sizeof *arr * rows);
if (arr)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < COLS; j++)
arr[i][j] = ...;
}
If you're working in C99, you can use a pointer to a VLA:
size_t rows, cols;
... // get rows and cols
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
arr[i][j] = ...;
}
How do we allocate a 2-D array using One malloc statement (?)
No answers, so far, allocate memory for a true 2D array.
int **array is a pointer to pointer to int. array is not a pointer to a 2D array.
int a[2][3] is an example of a true 2D array or array 2 of array 3 of int
To allocate memory for a true 2D array, with C99, use malloc() and save to a pointer to a variable-length array (VLA)
// Simply allocate and initialize in one line of code
int (*c)[nrows][ncolumns] = malloc(sizeof *c);
if (c == NULL) {
fprintf(stderr, "out of memory\n");
return;
}
// Use c
(*c)[1][2] = rand();
...
free(c);
Without VLA support, if the dimensions are constants, code can use
#define NROW 4
#define NCOL 5
int (*d)[NROW][NCOL] = malloc(sizeof *d);
You should be able to do this with (bit ugly with all the casting though):
int** array;
size_t pitch, ptrs, i;
char* base;
pitch = rows * sizeof(int);
ptrs = sizeof(int*) * rows;
array = (int**)malloc((columns * pitch) + ptrs);
base = (char*)array + ptrs;
for(i = 0; i < rows; i++)
{
array[i] = (int*)(base + (pitch * i));
}
I'm not a fan of this "array of pointers to array" to solve the multi dimension array paradigm. Always favored a single dimension array, at access the element with array[ row * cols + col]? No problems encapsulating everything in a class, and implementing a 'at' method.
If you insist on accessing the members of the array with this notation: Matrix[i][j], you can do a little C++ magic. #John solution tries to do it this way, but he requires the number of column to be known at compile time. With some C++ and overriding the operator[], you can get this completely:
class Row
{
private:
int* _p;
public:
Row( int* p ) { _p = p; }
int& operator[](int col) { return _p[col]; }
};
class Matrix
{
private:
int* _p;
int _cols;
public:
Matrix( int rows, int cols ) { _cols=cols; _p = (int*)malloc(rows*cols ); }
Row operator[](int row) { return _p + row*_cols; }
};
So now, you can use the Matrix object, for example to create a multiplication table:
Matrix mtrx(rows, cols);
for( i=0; i<rows; ++i ) {
for( j=0; j<rows; ++j ) {
mtrx[i][j] = i*j;
}
}
You should now that the optimizer is doing the right thing and there is no call function or any other kind of overhead. No constructor is called. As long as you don't move the Matrix between function, even the _cols variable isn't created. The statement mtrx[i][j] basically does mtrx[i*cols+j].
It can be done as follows:
#define NUM_ROWS 10
#define NUM_COLS 10
int main(int argc, char **argv)
{
char (*p)[NUM_COLS] = NULL;
p = malloc(NUM_ROWS * NUM_COLS);
memset(p, 81, NUM_ROWS * NUM_COLS);
p[2][3] = 'a';
for (int i = 0; i < NUM_ROWS; i++) {
for (int j = 0; j < NUM_COLS; j++) {
printf("%c\t", p[i][j]);
}
printf("\n");
}
} // end of main
You can allocate (row*column) * sizeof(int) bytes of memory using malloc.
Here is a code snippet to demonstrate.
int row = 3, col = 4;
int *arr = (int *)malloc(row * col * sizeof(int));
int i, j, count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*col + j) = ++count; //row major memory layout
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d ", *(arr + i*col + j));

dynamic allocating array of arrays in C

I don't truly understand some basic things in C like dynamically allocating array of arrays.
I know you can do:
int **m;
in order to declare a 2 dimensional array (which subsequently would be allocated using some *alloc function). Also it can be "easily" accessed by doing *(*(m + line) + column). But how should I assign a value to an element from that array? Using gcc the following statement m[line][column] = 12; fails with a segmentation fault.
Any article/docs will be appreciated. :-)
The m[line][column] = 12 syntax is ok (provided line and column are in range).
However, you didn't write the code you use to allocate it, so it's hard to get whether it is wrong or right. It should be something along the lines of
m = (int**)malloc(nlines * sizeof(int*));
for(i = 0; i < nlines; i++)
m[i] = (int*)malloc(ncolumns * sizeof(int));
Some side-notes:
This way, you can allocate each line with a different length (eg. a triangular array)
You can realloc() or free() an individual line later while using the array
You must free() every line, when you free() the entire array
Your syntax m[line][colummn] is correct. But in order to use a 2D array in C, you must allocate memory for it. For instance this code will allocated memory for a table of given line and column.
int** AllocateArray(int line, int column) {
int** pArray = (int**)malloc(line*sizeof(int*));
for ( int i = 0; i < line; i++ ) {
pArray[i] = (int*)malloc(column*sizeof(int));
}
return pArray;
}
Note, I left out the error checks for malloc for brevity. A real solution should include them.
It's not a 2d array - it's an array of arrays - thus it needs the multiple allocations.
Here's a modified version of quinmars' solution which only allocates a single block of memory and can be used with generic values by courtesy of void *:
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void ** array2d(size_t rows, size_t cols, size_t value_size)
{
size_t index_size = sizeof(void *) * rows;
size_t store_size = value_size * rows * cols;
char * a = malloc(index_size + store_size);
if(!a) return NULL;
memset(a + index_size, 0, store_size);
for(size_t i = 0; i < rows; ++i)
((void **)a)[i] = a + index_size + i * cols * value_size;
return (void **)a;
}
int printf(const char *, ...);
int main()
{
int ** a = (int **)array2d(5, 5, sizeof(int));
assert(a);
a[4][3] = 42;
printf("%i\n", a[4][3]);
free(a);
return 0;
}
I'm not sure if it's really safe to cast void ** to int ** (I think the standard allows for conversions to take place when converting to/from void * ?), but it works in gcc. To be on the safe side, you should replace every occurence of void * with int * ...
The following macros implement a type-safe version of the previous algorithm:
#define alloc_array2d(TYPE, ROWS, COLS) \
calloc(sizeof(TYPE *) * ROWS + sizeof(TYPE) * ROWS * COLS, 1)
#define init_array2d(ARRAY, TYPE, ROWS, COLS) \
do { for(int i = 0; i < ROWS; ++i) \
ARRAY[i] = (TYPE *)(((char *)ARRAY) + sizeof(TYPE *) * ROWS + \
i * COLS * sizeof(TYPE)); } while(0)
Use them like this:
int ** a = alloc_array2d(int, 5, 5);
init_array2d(a, int, 5, 5);
a[4][3] = 42;
Although I agree with the other answers, it is in most cases better to allocate the whole array at once, because malloc is pretty slow.
int **
array_new(size_t rows, size_t cols)
{
int **array2d, **end, **cur;
int *array;
cur = array2d = malloc(rows * sizeof(int *));
if (!array2d)
return NULL;
array = malloc(rows * cols * sizeof(int));
if (!array)
{
free(array2d);
return NULL;
}
end = array2d + rows;
while (cur != end)
{
*cur = array;
array += cols;
cur++;
}
return array2d;
}
To free the array simply do:
free(*array); free(array);
Note: this solution only works if you don't want to change the order of the rows, because you could then lose the address of the first element, which you need to free the array later.
Humm. How about old fashion smoke and mirrors as an option?
#define ROWS 5
#define COLS 13
#define X(R, C) *(p + ((R) * ROWS) + (C))
int main(void)
{
int *p = (int *) malloc (ROWS * COLS * sizeof(int));
if (p != NULL)
{
size_t r;
size_t c;
for (r = 0; r < ROWS; r++)
{
for (c = 0; c < COLS; c++)
{
X(r,c) = r * c; /* put some silly value in that position */
}
}
/* Then show the contents of the array */
for (r = 0; r < ROWS; r++)
{
printf("%d ", r); /* Show the row number */
for (c = 0; c < COLS; c++)
{
printf("%d", X(r,c));
}
printf("\n");
}
free(p);
}
else
{
/* issue some silly error message */
}
return 0;
}
Using malloc(3) for allocate the first array and putting in there pointers created by malloc(3) should work with array[r][c] because it should be equivalent to *(*(array + r) + c), it is in the C standard.

Resources