#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <tchar.h>
#include <string.h>
#include <math.h>
HANDLE wHnd; // Handle to write to the console.
HANDLE rHnd; // Handle to read from the console.
struct Terra {
int status;
CHAR_INFO display;
};
int main(){
int countX = 0;
int countY = 0;
int total = 0;
CHAR_INFO ScreenCon[10000];
int localcount = 0;
struct Terra *world= malloc(10000*sizeof(*world));
...
I have been using visual studio programing a screen console program that generate and display an 100 x 100 CHAR_INFO array. without using malloc(). My code is referenced from Ben Ryves' windows console tutorial.
The code without malloc() function is:
struct Terra world[100][100];
This code works perfectly but the compiler warns me that I should allocate memory for it. So I tried to integrated memory allocation in it and I learned that malloc() can't allocate 2d array directly, I can only do so by dividing my chunk of memory into 100 parts and use 1 extra array to store their location, my solution is to revert that 2d array into 1d and handle the data location with extra code. However, with reference to other question in stack overflow, I have change my code to the one above. But I got error code E0144 and C2440 at line 28, what have I done wrong?
Isn't that code is supposed to created a new pointer of struct Terra who called world then allocate 10000 x the size of single Terra is for it? How should I initialize an pointer before its declared??
I have read some information about malloc() but seem I don't understand how this really work. I would like to know what I have done wrong.
P.S.: I have done more tests and it seems the problem is that malloc() statement:
struct Terra {
int status;
CHAR_INFO display;
};
int main()
{
struct Terra* world = malloc(10000 * sizeof(*world));
return 0;
}
This code also returns the same error.
So, you want to have the equivalent of struct Terra world[100][100];, but allocated with malloc rather than having it on the stack, right?
I assume you know that you can allocate hundred objects of type foo like this:
foo *bar = malloc(100* sizeof(*bar));
bar is now a pointer to the first element of an array of 100 foo.
So in the world 2d array above you have an array of arrays of struct Terra of length 100. Basically, foo is an array of 100 struct world:
typedef struct Terra foo[100];
You can now allocate 100 of those arrays:
foo *world = malloc(100* sizeof(*world));
World now points to the first array of 100 struct Terra of 100 such arrays
Naturally, this can be done without a typedef:
struct Terra (*world)[100] = malloc(100* sizeof(*world));
I know this text may be a confusing mess of "arrays of arrays" but I hope you get the point.
Just an added comment on using malloc. When doing allocations like this: malloc(count * sizeof(*something)), be sure to make sure that the multiplication doesn't overflow. One of the biggest security bugs in the java virtual machine, was a failure to do such a check.
Correct/Valid solution:
If you want to access/iterate the 2D array like it got declared like struct Terra world[100][100];
Then you can alloc 100 diferent arrays, like this, and
struct Terra **world= malloc(100*sizeof(Terra*));
for(int i=0; i<100;i++){
world[i] = malloc(100*sizeof(Terra));
}
//the "usual" way to access the indexes
for(int i=0; i<100;i++)
for(int j=0; j<100;j++)
printf("%d ", world[i][j].status);
But if you want to use a singles continuous chunk o memory, you must allocate it like a 1D array, and access it doing some simple math:
size_t total_size = 100*100 //100 and 100 are the dimensions
struct Terra *world= malloc(total_size*sizeof(Terra));
//this way to access the indexes
for(int i=0; i<100;i++){
for(int j=0; j<100;j++){
//the formula to convert 2D indexes to a 1D array is: (i*N)+j, where N = number_of_columns
printf("%d ", world[i*100 + j].status);
}
}
wrong old answer
struct Terra **world= malloc(100*100*sizeof(Terra));
Related
This question already has answers here:
Large VLA overflow
(1 answer)
Getting a stack overflow exception when declaring a large array
(8 answers)
Closed 3 years ago.
I am trying to create a 2d array which each element points to a struct to store values from a CSV file. I am not sure if I am creating the struct or defining the 2d array right though.
Below is my struct and how I allocate the memory. There will always be 35 columns but the rows could grow quite large. When I run this with int test =29000 (or 29000 rows), it works and stores all values in a 2d array I can access by [row][col]. When I assign test with anything greater than 29000 it seg faults without even going into the allocation of the memeory it just segfaults at struct node* arrayofnodes[test][35];
I am very confused as to why it works with 29000 but not with 30000. Also, if anyone has any suggestions on how to malloc the array on one line instead of having to go into 2 for loops, I would be very happy to learn. Also I was wondering If I should use a typedef struct here or not.
Thanks
struct node {
char* value;
};
int test=30000;
struct node* arrayofnodes[test][35];
for (int p=0; p < test; p++){
for (int j=0; j < 35; j++){
arrayofnodes[p][j] = malloc(sizeof(arrayofnodes));
}
}//this works and i can access a certain element by arrayofnodes[row][col].value;
The problem is likely that you're allocating to much on the stack. arrayofnodes will be an array of 30,000*35=1,050,000 pointers, each of which is probably 8 bytes. So you're trying to allocate an array of 8MB on the stack, and 8MB is the default limit for stack size.
This code segfaulted for me:
#include <stdio.h>
int main() {
struct node {
char* value;
};
int test=30000;
struct node* arrayofnodes[test][35];
printf("%d\n", sizeof(arrayofnodes));
}
Also, sizeof(arrayofnodes) is wrong. If the code snippet above wouldn't have segfaulted, it would have printed 8400000. Instead, sizeof struct node or sizeof arrayofnodes[0][0] would give the right result.
A solution could be something like this:
struct node ** array[35];
for(int i=0; i<35; i++) {
array[i] = malloc(test * sizeof array[0]);
for(int j=0; j<test; j++) array[i][j] = malloc(sizeof (struct node));
}
You're allocating a huge amount of memory here: printf("%lu\n", sizeof(arrayofnodes)); reports that arrayofnodes has a size of 30000 * 35 * 8 = 8400000 bytes, making for a total memory allocation of 30000 * 35 * 8400000 = 8820000000000 bytes in your loop.
You might have meant *arrayofnodes[p][j]--allocate space for a pointer to a struct at row p and column j. Note that this doesn't include space for the memory block pointed to by the char *, which will also need to be malloced.
Also, remember that while the heap has plenty of space, the stack doesn't, and 8 * 35 * 30000 is likely more than a stack frame can handle.
Consider avoiding a struct if there's only one field. Using a plain old char * would avoid an extra layer of indirection.
If you'd like to maximize space efficiency at the expense of speed, you might try reading your text file in once to build an array of string sizes for each cell, then malloc everything accordingly for a second pass. You could use a char ***csv_data array containing cells allocated to size csv_cell_size[row][col] or similar.
Flattening your array by a dimension and using an offset to find a particular row/column is another option. Long story short, there are more than a few ways to manage this, with a lot depending on your data and how you plan to use it.
Also, don't forget to free() all your memory when you're done with it.
Your array declaration is being allocated on the stack, the default stack limit is 8MB. When test is 29000 the stack allocation is within the limit (29000 * 35 * 8 = 7.7MB), when you change test to 30000 you are exceeding the stack limit (30000 * 35 * 8 = 8.01MB) which results int the seg fault.
You can get past this by allocating the array on the heap using malloc, just remember to free what you allocate.
#include <stdio.h>
#include <malloc.h>
struct node {
char *value;
};
int rows = 30000;
int cols = 35;
struct node **arrayofnodes;
int main() {
arrayofnodes = (struct node **)malloc(rows * sizeof(struct node*));
for (int row = 0; row < rows; row++) {
arrayofnodes[row] = (struct node *)malloc(cols * sizeof(struct node*));
}
// Use arrayofnodes
// Free allocations after use...
}
I am trying to read a structure which contains another structure and then write it in a binary file. However, when i check if the structure was well read from the keyboard, the structure FIRMA is not read correctly. The value of 'nrang' is always 0 and the 'localitate' string is something very odd.
This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char localitate[10];
int nrang;
} FIRMA;
typedef struct
{
char nume[20];
int varsta;
FIRMA firma;
} ANG;
int main()
{
FILE* f;
ANG* a;
int n,i;
if ((f=fopen("fis.txt","wb"))==NULL) exit(1);
printf("number?\n");
scanf("%d",&n);
a=(ANG*)malloc(n*sizeof(ANG*));
printf ("Dati valorile");
for (i=0; i<n; i++)
{
scanf("%s%d",&a[i].nume,&a[i].varsta);
scanf("%s",&a[i].firma.localitate);
scanf("%d",&a[i].firma.nrang);
fwrite(&a[i],sizeof(a[0]),1,f);
printf("%s\n%d\n%s\n%d\n",a[i].nume,a[i].varsta,a[i].firma.localitate,a[i].firma.nrang);
}
}
Note that sizeof(ANG*) is not the same as sizeof(ANG) (the former is the size of the pointer -- probably 8 -- whereas the latter is the size of the structure -- probably 40), which means you're only allocating about 1/5 of the memory you intend to. As a result, the later code winds up writing and reading past the end of what's been allocated, which has undefined behavior.
One practice that helps people with this is to get into the habit of using sizeof(*ptr) when allocating for a pointer ptr, which will always give you the size of what it points to so you don't have to think of "do I need sizeof(ANG) or sizeof(ANG*) here?". This is particularly useful when allocating multi-dimensional arrays (e.g. int ***three_d_array = malloc(n * sizeof(*three_d_array))).
I'm writing a program that writes arrays and the information regarding them to a binary file.
My first approach was to call fwrite 4 times: once for general information regarding the array, once for the timestamp, once for the dimension of the array and once to write the array itself.
This approach worked as it is quite simple, but the execution times were too slow, seeing as the program is multithreaded and it writes to a SAS drive frequently, flooding the drive with requests which presented a bottleneck.
The new approach was to create an array of structs containing the information needed, my struct would be as follows:
struct array_data{
int information;
int timestamp;
int size;
int* data_array;
}
During execution I would write the data to a buffer and when I had everything I need it would call a malloc to allocate array_data.data_array and copy everything from the buffer from inside a for loop.
The issue is when I call fwrite to write the whole struct, the first 3 members of the struct are written correctly, while the array is not and that is due to the address of the array not being contiguous, since it points to another place in memory after the malloc.
The best solution to this would be to declare the data_array as a static array, this way the fwrite would work as I need it to, but then I would have to call fwrite for every struct, instead of calling it once to write an array of structs, which would impact the performance, negating the use of the struct.
I've also tried using an array of dynamically allocated structs, by declaring my struct as follows:
struct array_data{
int information;
int timestamp;
int size;
int data_array[];
}
and allocating the array of structs using malloc, but the address of struct_array[1].information is not the one right after the struct_array[0].data_array[last_index], there seems to be another 5 bytes in between, so if I were to call fwrite with struct_array the data in the file would still be incorrect.
Is there a way to use structs to solve this issue or should I just stick with writing my arrays to the file as I did in the first place?
The following example creates, writes and reads your data. It is just a outline. Error checks on malloc, fread and fwrite ommitted:
#define N_DATA 10
#define N_INTS 5
struct array_data{
int information;
int timestamp;
int size;
int* data_array;
};
struct array_data arr[N_DATA];
void makeData(void){
int i;
for (i=0;i<N_DATA;i++) {
arr[i].data_array=malloc(N_INTS*sizeof(int));
arr[i].size= N_INTS;
}
}
void writeData(FILE *fp_out)
{
int i;
for (i=0;i<N_DATA;i++) {
fwrite(&arr[i],sizeof(arr[i]),1,fp_out);
fwrite(arr[i].data_array,arr[i].size*sizeof(int),1,fp_out);
}
}
void readData(FILE *fp_in)
{
int i= 0;
while(fread(&arr[i],sizeof(arr[i]),1,fp_in)==1) {
arr[i].data_array=malloc(arr[i].size*sizeof(int));
fread(arr[i].data_array,arr[i].size*sizeof(int),1,fp_in);
i++;
}
}
I am loading some data into struct.
struct test {
char x[101];
char y[101];
int z;
};
Then I create memory for structs
struct test * data;
data = malloc(10 * sizeof(struct test));
And fill data like this
data[0].z = 123;
This works alright. But I wanna sort these structs. Like sort them depending on z attribute.
My idea was to create a new array and fill it with pointers which will point to the right struct.
Can somebody tell me how or if there is better way?
Thanks
This depends on your goal. If you are trying to figure out what would be most programmer efficient, then creating an ordering functor based on the z attribute of your struct, and sorting the list directly, is easiest.
However, if you are concerned with program efficiency, then it will be faster to sort pointers, as suggested by Fiddling Bits. However, you must keep in mind that this will give you a sorted list of pointers- your data array will still be in the same order.
For instance, if datapoints is your array of pointers, and you wanted to sort by the z value, you could define the comparison
int compare(const void *a, const void *b)
{
return ( (*(test *)a).z -(*(test *)b).z );
}
And then call
qsort( datapoints, 10, sizeof(test), compare);
Full documentation for qsort can be found here:
One way to do this is using qsort, the general sorting algorithm provided in the standard library for sorting sequences of user-defined data. With a goal of doing the following:
the source data must remain un-touched.
the "sorted" access must be provided via a list of pointers to the untouched data from above
this is one way to do that using the qsort() standard library function:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
struct test {
char x[101];
char y[101];
int z;
};
int cmp_test_ptrs(const void* arg1, const void* arg2)
{
struct test const * lhs = *(struct test const * const*)arg1;
struct test const * rhs = *(struct test const * const*)arg2;
return (lhs->z < rhs->z) ? -1 : (rhs->z < lhs->z);
}
int main()
{
srand((unsigned int)time(0));
// populate data array.
struct test * data = malloc(10 * sizeof(*data));
for (int i=0; i<10; ++i)
{
data[i].z = rand() % 20;
printf("%d ", data[i].z);
}
printf("\n");
// allocate a pointer array to use as a sort-bed, copying each
// structure address into this pointer array afterward
struct test **ptrs = malloc(10 * sizeof(*ptrs));
for (int i=0; i<10; ++i)
ptrs[i] = data+i;
// sort the pointer bed using our comparator
qsort(ptrs, 10, sizeof(*ptrs), cmp_test_ptrs);
// ptrs now has sorted pointers. Note the dereference for access
// to the actual data, which remains where it originally was.
for (int i=0; i<10; ++i)
printf("%d ", ptrs[i]->z);
printf("\n");
free(ptrs);
free(data);
return 0;
}
Sample Output
11 7 6 17 8 8 11 4 7 5
4 5 6 7 7 8 8 11 11 17
Important to note is the original structure array remained untouched. We sorted a sequence of pointers, not the actual structures themselves, and used what those pointers pointed-to as the criteria for the sort.
Anyway, I hope it helps. Study the comparator and the setup for qsort() carefully. They're important. You can read more about qsort() here.
Or you can just sort them in the same array and probably save some memory (4 bytes for a pointer of any type) :P
Doesn't really matter though, pointers'll work fine I guess.
But I think that in some cases pointers will be more useful as if you would sort it in the array you'll need a temporary struct defined to contain structs when you're sorting and if you're struct is big than you'll actually take a lot more memory than 4 bytes.
+Also remember that when defining a pointer to a struct - access it with -> operator.
Usage: STRUCT_POINTER_NAME->VARIABLE
I am working with a 2-dimensional array of structs which is a part of another struct. It's not something I've done a lot with so I'm having a problem. This function ends up failing after getting to the "test" for-loop near the end. It prints out one line correctly before it seg faults.
The parts of my code which read data into a dummy 2-d array of structs works just fine, so it must be my assigning array to be part of another struct (the imageStruct).
Any help would be greatly appreciated!
/*the structure of each pixel*/
typedef struct
{
int R,G,B;
}pixelStruct;
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
imageStruct ReadImage(char * filename)
{
FILE *image=fopen(filename,"r");
imageStruct thisImage;
/*get header data from image*/
/*make a 2-d array of of pixels*/
pixelStruct imageArr[thisImage.height][thisImage.width];
/*Read in the image. */
/*I know this works because I after storing the image data in the
imageArr array, I printed each element from the array to the
screen.*/
/*so now I want to take the array called imageArr and put it in the
imageStruct called thisImage*/
thisImage.arr = malloc(sizeof(imageArr));
//allocate enough space in struct for the image array.
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*/
//test to see if assignment worked: (this is where it fails)
for (i = 0; i < thisImage.height; i++)
{
for (j = 0; j < thisImage.width; j++)
{
printf("\n%d: R: %d G: %d B: %d\n", i ,thisImage.arr[i][j].R,
thisImage.arr[i][j].G, thisImage.arr[i][j].B);
}
}
return thisImage;
}
(In case you are wondering why I am using a dummy array in the first place, well it's because when I started writing this code, I couldn't figure out how to do what I am trying to do now.)
EDIT: One person suggested that I didn't initialize my 2-d array correctly in the typedef for the imageStruct. Can anyone help me correct this if it is indeed the problem?
You seem to be able to create variable-length-arrays, so you're on a C99 system, or on a system that supports it. But not all compilers support those. If you want to use those, you don't need the arr pointer declaration in your struct. Assuming no variable-length-arrays, let's look at the relevant parts of your code:
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
arr is a pointer to pixelStruct, and not to a 2-d array of pixels. Sure, you can use arr to access such an array, but the comment is misleading, and it hints at a misunderstanding. If you really wish to declare such a variable, you would do something like:
pixelStruct (*arr)[2][3];
and arr would be a pointer to an "array 2 of array 3 of pixelStruct", which means that arr points to a 2-d array. This isn't really what you want. To be fair, this isn't what you declare, so all is good. But your comment suggests a misunderstanding of pointers in C, and that is manifested later in your code.
At this point, you will do well to read a good introduction to arrays and pointers in C, and a really nice one is C For Smarties: Arrays and Pointers by Chris Torek. In particular, please make sure you understand the first diagram on the page and everything in the definition of the function f there.
Since you want to be able to index arr in a natural way using "column" and "row" indices, I suggest you declare arr as a pointer to pointer. So your structure becomes:
/* data for each image */
typedef struct
{
int height;
int width;
pixelStruct **arr; /* Image data of height*width dimensions */
} imageStruct;
Then in your ReadImage function, you allocate memory you need:
int i;
thisImage.arr = malloc(thisImage.height * sizeof *thisImage.arr);
for (i=0; i < thisImage.height; ++i)
thisImage.arr[i] = malloc(thisImage.width * sizeof *thisImage.arr[i]);
Note that for clarity, I haven't done any error-checking on malloc. In practice, you should check if malloc returned NULL and take appropriate measures.
Assuming all the memory allocation succeeded, you can now read your image in thisImage.arr (just like you were doing for imageArr in your original function).
Once you're done with thisImage.arr, make sure to free it:
for (i=0; i < thisImage.height; ++i)
free(thisImage.arr[i]);
free(thisImage.arr);
In practice, you will want to wrap the allocation and deallocation parts above in their respective functions that allocate and free the arr object, and take care of error-checking.
I don't think sizeof imageArr works as you expect it to when you're using runtime-sized arrays. Which, btw, are a sort of "niche" C99 feature. You should add some printouts of crucial values, such as that sizeof to see if it does what you think.
Clearer would be to use explicit allocation of the array:
thisImage.arr = malloc(thisImage.width * thisImage.height * sizeof *thisImage.arr);
I also think that it's hard (if even possible) to implement a "true" 2D array like this. I would recommend just doing the address computation yourself, i.e. accessing a pixel like this:
unsigned int x = 3, y = 1; // Assume image is larger.
print("pixel at (%d,%d) is r=%d g=%d b=%d\n", x, y, thisImage.arr[y * thisImage.width + x]);
I don't see how the required dimension information can be associated with an array at run-time; I don't think that's possible.
height and width are undefined; you might want to initialise them first, as in
thisImage.height = 10; thisImage.width = 20;
also,
what is colorRGB?
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*
This won't work. You have to declare arr as colorRGB **, allocate it accordingly, etc.
it looks like you are trying to copy array by assignment.
You cannot use simple assignment operator to do that, you have to use some function to copy things, for example memcpy.
*thisImage.arr = *imageArr;
thisimage.arr[0] = imagearr[0];
The above statements are doing the same thing.
However this is not most likely what causes the memory corruption
since you are working with two dimensional arrays, do make sure you initialize them correctly.
Looking at the code, should not even compile: the array is declared as one-dimensional in your image structure but you refer to as two-dimensional?