2d array of struct -- malloc() and free() - c

#pragma pack(push, 1)
typedef struct
{
/*...*/
unsigned int dataoffset; //No of bytes before actual pixel data
}HEADER;
typedef struct
{
/*...*/
unsigned int width;
unsigned int height;
unsigned short bits_per_pixel; //code is written for 24 bits only and No other format is supported..
/*...*/
}INFO_HEADER;
typedef struct
{
unsigned char b;
unsigned char g;
unsigned char r;
}COLORMAP;
#pragma pack(pop)
int main()
{
// Var decl.
INFO_HEADER *pHeader = NULL;
FILE *pImage;
COLORMAP **ppColors;
/*...*/
/* File opened in read, binary mode, memory allocated for pHeader*/
fread (pHeader, sizeof(INFO_HEADER), 1, pImage);
/*Next block is actually problematic.. Posting 'as is' from my code*/
ppColors = (COLORMAP**)malloc((pHeader -> height ) * sizeof(COLORMAP));
for(i = 0 ; i < pHeader -> height ; i++)
ppColors[i] = (COLORMAP*)malloc(pHeader -> width * sizeof(COLORMAP));
fseek(pImage, pHeader -> fileheader.dataoffset, SEEK_SET);
for (i = 0 ; i < pHeader -> width ; i++)
{
for (j = 0 ; j < pHeader -> height ; j++)
{
fread(&b, sizeof(unsigned char), 1, pImage);
fread(&g, sizeof(unsigned char), 1, pImage);
fread(&r, sizeof(unsigned char), 1, pImage);
ppColors[i][j].b = b;
ppColors[i][j].g = g;
ppColors[i][j].r = r;
printf("width = %d height = %d %d:\t", i, j, cnt);
printf("%d ", (int)ppColors[i][j].b);
printf("%d ", (int)ppColors[i][j].g);
printf("%d\n", (int)ppColors[i][j].r);
cnt++;
}
}
/*And at last free()ing..*/
for(i = 0 ; i < pHeader -> height ; i++) free(ppColors[i]);
free(ppColors);
cleanup();
return(0)
}
Possible Duplicate: http://stackoverflow.com/questions/1568042/optimal-way-to-free-a-malloced-2d-array-in-c
Though above link could not solve my problems.
I run out of memory. I have malloc()ed for height, then for each of the height, width is again malloc()ed. I am trying to work on width X height domain only. It seems that problem is with height. If you change
ppColors = (COLORMAP**)malloc((pHeader -> height ) * sizeof(COLORMAP)); to
ppColors = (COLORMAP**)malloc((pHeader -> height + 6 ) * sizeof(COLORMAP));
Then this problem disappears.
But then at the time of free()ing I get double free / corruption at core dump.
I am damn sure I am going wrong somewhere. I do not expect someone to correct my code and I just run it. Just hints would do.

A pointer to a pointer is not the same as an array of arrays.
When using a pointer-to-pointer to simulate a multi-dimensional array, like this declaration:
char **pointer;
the memory looks like this:
+------------+------------+-----+-------------------+
| pointer[0] | pointer[1] | ... | pointer[size - 1] |
+------------+------------+-----+-------------------+
| | |
v v v
Data Data Data
While a proper multi-dimensional array
char array[X][Y];
looks like this in memory:
+-------------+-------------+-----+-----------------+-------------+-----+
| array[0][0] | array[0][1] | ... | array[0][Y - 1] | array[1][0] | ... |
+-------------+-------------+-----+-----------------+-------------+-----+
So in a proper multi-dimensional array all the memory is in one single block, while using pointer-to-pointer you have an array of pointers and not an array of arrays.
So what you should do is allocate all sub-arrays separately:
ppColors = malloc(pHeader->height * sizeof(COLORMAP *));
/* Note how I allocate the width times the size of a COLORMAP pointer */
for (int i = 0; i < pHeader->height; i++)
ppColors[i] = malloc(pHeader->width * sizeof(COLORMAP));
Don't forget that you now have to call free in a loop too!

I can see a couple of problems:
ppColors is an array of pointers. Each element in the array is a COLORMAP* so you need to calculate the size to be malloced using numElements * sizeof(COLORMAP*). COLORMAP is just 3 chars so its likely that sizeof(COLORMAP*) > sizeof(COLORMAP). Your current allocation will be too small so you'll end up writing beyond the end of the array; this has undefined effects but is likely to crash.
use of width & height are reversed between allocations and loops so you'll end up writing to unallocated memory at some point in your loops.

This may not be an answer but probably help you along with other answers.
This might be problem with fread check what do you get in pHeader -> height and pHeader -> width
Use parenthesis around pHeader -> width in malloc(pHeader -> width * sizeof(COLORMAP))

Related

Can I assign the address of shared memory to a pointer directly?

I'm trying to create a shared memory for IPC. I want to put a structure with dynamic 2D array in it into the shared memory. Here is the structure.
/* struct with 2 2D arrays. */
struct _test {
uint16_t **A;
uint16_t **B;
} test;
I know that a double pointer is not actually a 2D array and I should use a pointer to array like int (*ptr)[3], but the problem is that I can only get the size of the 2D array during runtime. So I have to declare the 2D array this way(at least what I know of).
Then I calculate the size of those two arrays in run time, say they both are 2x2 arrays, which takes 16 bytes(uint16_t is 2 byte). So I did this:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
size_t size = 16; //size of two uint16_t 2D arrays.
key_t key;
key = ftok("dev/null", 1);
int s_shm_id = shmget(key, size, IPC_CREAT|0600); //get 16 bytes of shared memory.
test *shm = (test*)shmat(s_shm_id,(const void*)0,0); //attach it.
//I want pointers in this struct to point at shared memory.
test *ptr = malloc(sizeof(test));
//Array A starts at the beginning of shared memory.
ptr -> A = (uint16_t **)shm; //My main confusion is here. Is this right?
int i;
for(i=0; i<2; i++)
ptr->A[i] =(uint16_t *)((uint16_t *)ptr->A + i*2);
//Array B starts right after A.
ptr -> B = ptr -> A[i-1] + 2;
for(i=0; i<2; i++)
ptr -> B[i] = (uint16_t *)((uint16_t *)ptr->B + i*2);
}
I understand this is basically wrong, I got segfault, but how? What a pointer needs is an address to point at, since I have already created a space(using shmget), why can't I make a pointer to point at it? Thanks for any feed back in advance!
What you are after are "jagged" or "scattered" arrays, not "linear" arrays. A scattered 2D-array in fact is not one array, but 1+N arrays, with N being the dimension of the 2D-matrix you are after.
The code you show misses to allocated this 1 array inside "1+N".
Assuming you successfully allocated enough memory to hold two 2D arrays with dimension N of uint16_t, that is 2 * N*N * sizeof (uint16_t) bytes, then the code to prepare the access to this memory might look like this (error checking left out for readability):
void * p = ... /* Allocate memory here; does not necessarily needs to be SHM. */
uint16_t ** A = malloc(N * sizeof *A);
for (size_t i = 0; i < N; ++i)
{
A[i] = ((uint16_t*) p) + i*N;
}
uint16_t ** B = malloc(N * sizeof *B);
for (size_t i = N; i < 2*N; ++i)
{
B[i - N] = ((uint16_t*) p) + i*N;
}
/* Access A[0 .. N-1][0 .. N-1] and B[0 .. N-1][0 .. N-1] here ... */
Placing A and B inside a struct which in turn is allocated dynamically is left to you as an exercise.
Accessing the arrays' elements is done straight forward: A[0][0] accesses the 1st array's 1st row's 1st element.
For clarity the same code for NxM arrays
uint16_t ** A = malloc(N * sizeof *A);
for (size_t i = 0; i < N; ++i)
{
A[i] = ((uint16_t*) p) + i*M;
}
uint16_t ** B = malloc(N * sizeof *B);
for (size_t i = N; i < 2*N; ++i)
{
B[i - N] = ((uint16_t*) p) + i*M;
}

how to change the value stored in a VLA which is in a struct

I have the following structure im using to encode a PPM file with a message using steganography:
typedef struct{
char code[CODE_LENGTH];
COMMENT *commentPPM;
int width, height, max;
COLOR (*colorValues)[];
} PPM;
and the color:
typedef struct{
unsigned char red, green, blue;
} COLOR;
and method:
PPM *encode(char *text, PPM *img){
//tested
printf("entered encode\n");
PPM *newPPM;
newPPM = duplicate(img);
printf("duplicated ppm\n");
int x,y, currentChar, textLength;
textLength = strlen(text);
////
for(currentChar = x = y = 0; currentChar < textLength; currentChar++){
printf("the current character is %c\n", *(text+currentChar));
//between 1 and the width
x += (rand() % (newPPM->width -1)) + 1;
printf("generated %d for x\n",x);
if(x >= newPPM->width){
printf("%d is greater than width(%d)\n",x,newPPM->width);
x -= newPPM->width;
printf("%d is the new x\n", x);
y++;
printf("incremented y to be %d\n", y);
}
newPPM->colorValues[y][x].red = text[currentChar]; //error (1)
printf("changed the value of color[%d][%d].red, to be %d, which is %c\n",y,x, text[currentChar], text[currentChar]);
}
return newPPM;
}
How do you access for example "red" within the pointer to the 1d array seen at (1)?
Edit: I get the error message:
"error: invalid use of array with unspecified bounds
newPPM->colorValues[y][x].red = text[currentChar];"
Edit 2: I'm hearing that I cannot access the elements of colorValues in
typedef struct{
char code[CODE_LENGTH];
COMMENT *commentPPM;
int width, height, max;
COLOR (*colorValues)[];
} PPM;
as it hasn't got the width specified so i cant determine the offset. However I this is just a pointer to a flexible array member is getting assigned a type
ppmFile->colorValues = getColors(fd, ppmFile->width, ppmFile->height);
COLOR (*getColors(FILE *fd, int width, int height))[]{
COLOR (*colors)[width] = (COLOR(*)[width]) malloc(sizeof(COLOR[height][width]));
int i,j;
for(i = 0; i < height; i++) {
for(j = 0; j < width; j++) {
fscanf(fd,"%d %d %d", &colors[i][j].red, &colors[i][j].green, &colors[i][j].blue);
}
}
return colors;
}
which has got the width specified. So if I'm understanding correct when I am passing this back to be stored in the struct i am "losing" the offset (width). However When I am in the encrypt method, I have access to the width, height, and current x and y positions, surely there is a way of telling the compiler that this flexible array member has the offset of width,I did do this in the printColors method and it worked fine (see bellow), why cant I tell the compiler that the values stored in newPPM->colorValues have the offset of width?
void printColors(int width, int height, COLOR (*colors)[width]){
int n, j;
for(n = 0; n < height; n++) {
for(j = 0; j < width; j++) {
printf("%d %d %d\n", colors[n][j].red, colors[n][j].green, colors[n][j].blue);
}
}
}
is there a way of casting the newPPM->colorValues to tell it to have the offset width? Like I did with colors in printColors
You're probably getting an error like:
prog.c:10:14: error: subscript of pointer to incomplete type 'struct foo []'
thing->foos[0][0].bar;
~~~~~~~~~~~^
1 error generated.
For reference, the above is the output of compiling this code:
struct foo { int bar; };
struct baz {
struct foo (*foos)[];
};
int main () {
struct baz * thing;
thing->foos[0][0].bar;
return 0;
}
(Live)
What the compiler is trying to tell you is that it cannot compute the offset needed to access subsequent elements of the outer array. The reason is that it doesn't know the size of the array elements (as they're of incomplete type, that is lacking size information).
Basically, it's trying to compute (the following is a pseudo language, not C)
thing + offset(foos) + 0 * sizeof(struct foo[]) + 0 * sizeof(struct foo) + offset(bar)
but it can't because it doesn't know sizeof(struct foo[]).
The root of this issue is that your trying to have a pointer to a variable length array in the first place. Changing the member to
struct foo (*foos)[42];
"solves" this by giving the arrays dome size.
If you want a 2D array just make it 1D, appending all inner arrays. (Of course this works only if they're of the same size, i.e. if you want a rectangular 2D array)
struct foo * grid = malloc (sizeof (struct foo) * rows * columns);
// access using grid [c * rows + r]
You can access 2D data in a 1D array by calculating the array index formula yourself.
buf[ width*y + x ];
where width needs to be the stride in units of the buffer type.

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

Access violation reading location location 0x1D5C4C2F

This function is throwing an access violation when reading raw pixel values and I can't figure out why.
Can consider this as the only part of my code running, I've run this solo with the same result.
string filenames[]={"firstclick.raw", "secondclick.raw","thirdclick.raw","fourthclick.raw","fifthclick.raw","sixthclick.raw","seventhclick.raw","eighthclick.raw"};
FILE *file;
int height= 750, width = 453, bbp=3;
unsigned char ****images;
images = (unsigned char ****)malloc(sizeof(unsigned char ***)*8);
for(int j = 0; j<8; j++){
images[j] = (unsigned char ***)malloc(sizeof(unsigned char**)*height);
for(int i = 0; i<height; i++){
images[j][i]= (unsigned char **)malloc(sizeof(unsigned char*)*width);
for(int k = 0; k<bbp; k++)
images[j][i][k]= (unsigned char *)malloc(sizeof(unsigned char)*bbp);
}
}
for (int i = 0; i<8; i++){
if (!(file=fopen(filenames[i].c_str(),"rb"))){
cout << "Cannot open file: "<<filenames[i].c_str() <<endl;
exit(1);
}
fread(images[i], sizeof(unsigned char), height*width*bbp, file);
fclose(file);
}
The problem here is you've allocated each element of your array as a separate array (somewhere else in memory, whose location is kept as a pointer). But when you read in, you assume that it's a single contiguous block. You will overwrite all those pointers, and overflow the buffer to boot.
If you want images to be a set of discrete blocks of memory, allocate like this:
unsigned char ** images;
int i;
images = malloc( sizeof(unsigned char *) * 8 );
for( i = 0; i < 8; i++ ) {
images[i] = malloc( width * height * bpp );
}
Note that sizeof(unsigned char) is defined by the standard to always be 1. You don't need to multiply by sizeof(unsigned char) all the time.
Now, to get a pixel address in an image, you need to multiply out (usually row-major):
unsigned char * pixel = images[i] + (y * width + x) * bpp;
unsigned char r = pixel[0];
unsigned char g = pixel[1];
unsigned char b = pixel[2];
when you allocate the memory blocks in different locations in memory an fread on that structure will not work.
instead allocate one big block then set the pointers to point inside the block, that way you can use fread on it.

How do I allocate a 2 D array with contigious memory ? How Do I use it to access rows and columns? Give me an example

I have created a 2 d array which reads as follows
int i,j,lx,ly;// lx,ly are the row and column respectively
double** a;
a=(double**) malloc((lx+2)*sizeof(double));
a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double));
assert(a[0]);
for(i=1;i<lx+2;i++)
{
a[i]=a[i-1]+i*(ly+2);
}
// I allocate a value of 0 to all the elements in this array as below
for(i=0;i<(lx+2)*(ly+2);i++)
{
a[i]=0;
}
// I print out all my elements below
for(i=0;i<(lx+2)*(ly+2);i++)
{
printf("position %d values %d\n",i,a[i]);
}
// When I see the output , it shows me a junk value at one particular position 13. I am unable to figure that out .. ALso kindly tell me how to access rows and columns like Eg to acces 7 th column row 0 and 5th row 6 th column in terms of lx, ly as shown in my code
Your approach is definitely heading in the right general direction.
I think this:
a=(double**) malloc((lx+2)*sizeof(double));
would normally be:
a = malloc(lx * sizeof(double *));
And then without the contiguity requirement, this:
a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double));
in most programs would look like:
a[0] = malloc(ly * sizeof(double));
And finally, that last line needs to be in a loop that assigns each a[i] with it's own malloc'ed space.
However, that won't create contiguous memory. To do that you will need to do that big allocation and then divide it up for the row vector. So, instead of the second malloc in a loop, perhaps something like:
double *t = malloc(lx * ly * sizeof(double));
for (i = 0; i < lx; ++i)
a[i] = t + i * ly;
Putting it all together:
#include <stdio.h>
#include <stdlib.h>
void arrayDemo(int lx, int ly)
{
double **a;
int i, j;
a = malloc(lx * sizeof(double *));
double *t = malloc(lx * ly * sizeof(double));
for(i = 0; i < lx; ++i)
a[i] = t + i * ly;
for(i = 0; i < lx; ++i)
for(j = 0; j < ly; ++j)
a[i][j] = i*100 + j;
for(i = 0; i < lx; ++i) {
for(j = 0; j < ly; ++j)
printf(" %4.0f", a[i][j]);
printf("\n");
}
}
int main(int ac, char **av)
{
arrayDemo(atoi(av[1]), atoi(av[2]));
return 0;
}
$ cc -Wall all.c
$ ./a.out 4 7
0 1 2 3 4 5 6
100 101 102 103 104 105 106
200 201 202 203 204 205 206
300 301 302 303 304 305 306
This code allocates a 10 by 5 contiguous block of memory, initializes it with incrementing doubles, and then prints the values indexed by x and y:
#include "2d.h"
int main(void){
unsigned int x,y;
const unsigned int width = 10;
const unsigned int height = 5;
//we need an index into the x of the array
double * index[width];
//need the memory to store the doubles
unsigned int memorySizeInDoubles = width * height;
double * memory = malloc(memorySizeInDoubles * sizeof(double));
//initialize the memory with incrementing values
for(x = 0; x < memorySizeInDoubles; ++x){
memory[x] = (double) x;
}
//initialize the index into the memory
for(x = 0; x < width; ++x){
index[x] = memory + height * x;
}
//print out how we did
for(x = 0; x < width; ++x){
for(y = 0; y < height; ++y){
printf("[%u, %u]: Value = %f\n", x, y, index[x][y]);
}
}
free(memory);
return 0;
}
The 2d.h file should contain these lines:
#include <stdio.h>
#include <stdlib.h>
int main(void);
Note: The memory created is only contiguous for some definitions. The memory is logically contiguous, but not necessarily physically contiguous. If this memory is for a device driver for instance, malloc won't work.
Either you create a single dimension array
double my_array = malloc(sizeof(double) * size_x * sizeof(double) * size_y);
which you will access by
(get position x=28, y=12)
my_array[12 * size_x + 28];
or you create a 2d array like you do, but you access it with
double **my_array = (double**) malloc(15 * sizeof(double));
for(int i = 0 ; i < 25; i++)
{
my_array[i] = (double*) malloc(30 * sizeof(double));
for (int j = 0 ; j < 12; j++)
{
my_array[i][j] = 1.2;
}
}
double my_double = my_array[12][28];
In C, to have one chunk of contiguous memory, you need one malloc(), or have a statically allocated array. Since you want dynamic memory, you will need malloc(). Since you need everything to be contiguous, you will need only one call to it.
Now, what should the call look like? If I understood you correctly, you need lx times ly values, each with size sizeof(double), so you need lx*ly*sizeof(double) bytes to be allocated.
Digression: I prefer writing my malloc() calls as follows:
#include <stdlib.h> /* for malloc's prototype */
T *pt; /* for any type T */
size_t n; /* need n objects of type T */
pt = malloc(n * sizeof *pt);
Using sizeof with sizeof *pt instead of sizeof(T) offers an advantage that if the type of pt changes, you don't need to change the malloc() call. Not casting the result of malloc() is nice because then the whole malloc() call is type-agnostic, and is easier to type and read. Be sure to #include <stdlib.h> though.
So, to allocate space for n doubles, you can do:
double *pd = malloc(n * sizeof *pd);
if (pd != NULL) {
/* malloc succeeded */
} else {
/* malloc failed */
}
Now, after allocating memory, you need to be able to index it. Let's say you have lx == 2 and ly == 3. Your memory looks like:
+---+---+---+---+---+---+
pd: | 0 | 1 | 2 | 3 | 4 | 5 |
+---+---+---+---+---+---+
pd[0], pd[1] and pd[2] are the double values corresponding to the first row, pd[3] to pd[6] are the double values corresponding to the second row. You should be able to generalize this observation to translate a given x,y index pair to one number that indexes into your pd array properly.

Resources