I have the following code snippet, which is giving me segmentation fault.
#include <stdio.h>
#include <stdlib.h>
struct node {
unsigned int n1;
unsigned int n2;
};
int main() {
struct node *nd = (struct node *)malloc(24356 * sizeof(struct node));
for(int i=0; i < 24356; i++) {
nd[i * sizeof(struct node)].n1 = i;
nd[i * sizeof(struct node)].n2 = i+1;
}
return 0;
}
When I did some debugging, I could find that the for loop was executing for some 3000 times, and then the segmentation fault occurs on this line:
nd[i * sizeof(struct node)].n1 = i;
I couldn't understand what is wrong in this code.
Can't malloc() allocate the amount of memory (~190 KB) I am asking it to allocate ?
If so, why doesn't it return NULL ?
These lines are the problem:
nd[i * sizeof(struct node)].n1 = i;
nd[i * sizeof(struct node)].n2 = i+1;
Change them to:
nd[i].n1 = i;
nd[i].n2 = i+1;
Remember, indices are not byte offesets. They're element indices. The compiler will automatically scale them by the size of an element.
I couldn't understand what is wrong in this code. Can't malloc() allocate the amount of memory (~190 KB) I am asking it to allocate ? If so, why doesn't it return NULL ?
There are several misunderstandings in your interpretation of the use of malloc that make your code incorrect:
malloc is a generic library routine that needs as parameter the amount of bytes to allocate and you correctly ask for space for 24356 cells by the size of one cell (64 bytes) or 1,558,784 bytes. (Around 1,5Mb, and not the 190kb you say in the question)
Then, you access the array elements by byte offset, this time erroneusly, as you have defined an array of structs, you cannot get the 24,356 (and later) array elements.
The expression you use inside the array index can range only from 0 to 24355, and no more.
Change
nd[i * sizeof(struct node)].n1 = i;
by
nd[i].n1 = i;
As arrays must be indexed by element position, and not by element address (respect to array origin)
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 allocate blocks of memory for my program. I need to allocate 8 blocks of memory each having 62500bytes ( sizeof Int * 32 ) . In a way I am allocating 2,000,000 bit for each block (total number of blocks are 8).
I tried using int *a= (int*) calloc(62500 * 8, sizeof(int)) and I use
int i=0;
for (i = 0; i < 62500 * 8; i++) {
blk[i] = i;
}
I use the above to allocate a value to each address so that it is easy to keep track of which index I need to fetch, since unlike array which are consecutive blocks of memory , if I use calloc I do not get consecutive memory addresses. But my problem here is I want each of 8 blocks allocated with a start index as 0 and end as 62500.Like block1(0...62500) , block2(0...62500),block3(0...62500) ... block8(0...62500). I am not sure how to get this kind of structure.
I started with something like:
typedef struct block {
int b;
} blk;
How do I make a struct *blk = {block1,block2,block3...block8}, So that I can reach to each block from pointer *blk.
Thanks
Get a pointer to an array of arrays.
#define BLK_SZ 62500
#define BLK_NMEMB 8
The parentheses here denote that blk is a pointer to an array, rather than an array of pointers.
int (*block)[BLK_SZ][BLK_NMEMB] = calloc(62500 * 8, sizeof(int));
Note that the cast is unnecessary because void * is guaranteed to convert to any other pointer type. Now you can address it like:
(*block)[0][9001] = 14;
You can also create a typedef:
typedef int blk[BLK_SZ][BLK_NMEMB];
Which can then be used as:
blk *block = calloc(BLK_SZ * BLK_NMEMB, sizeof(int));
and addressed in the same manner as above.
If you really must, you can do:
typedef struct {
int block0[BLK_SZ];
int block1[BLK_SZ];
int block2[BLK_SZ];
int block3[BLK_SZ];
int block4[BLK_SZ];
int block5[BLK_SZ];
int block6[BLK_SZ];
int block7[BLK_SZ];
} blk;
and:
blk *block = calloc(BLK_SZ * BLK_NMEMB, sizeof(int));
accesed by
(*block).block0[9001] = 14;
I wrote a C code that usea a matrix of double:
double y[LENGTH][4];
whith LENGTH=200000 I have no problem.
I have to increase the numbers of rows to LENGTH=1000000 but when I enter this value and execute the program it returns me segmentation fault.
I tried to allocate more memory using malloc:
double **y = (double **)malloc(LENGTH * sizeof(double*));
for(int i = 0; i < LENGTH; i++){
y[i] = (double *)malloc(4 * sizeof(double));
}
I run the the code above and after some second of calculations it still gives me "segmentation fault".
Could anyone help me?
If you want a dynamic allocated 2D array of the specified row-width, just do this:
double (*y)[4] = malloc(LENGTH * sizeof(*y));
There is no need to malloc each row in the matrix. A single malloc and free will suffice. Only if you need dynamic row width (each row can vary in width independent of others) or the column count is arbitrary should a nested malloc loop be considered. Neither appears to be your case here.
Notes:
Don't cast malloc in C programs
Be sure to free(y); when finished with this little tryst.
The reason your statically allocated array is segfaulting with a million elements is (presumably) because it's being allocated on the stack. To have your program have a larger stack, pass appropriate switches to your compiler.
ProTip: You will experience less memory fragmentation and better performance if you flip your loop around, allocating
(double *)malloc(LENGTH * sizeof(double));
four times. This will require changing the order of your indices.
I ran the the code with this definition and after some second of calculations it still gives me "segmentatin fault"
If you're getting a segmentation fault after allocating the memory, you're writing outside of your memory bounds.
I run this code
#include <stdio.h>
#include <stdlib.h>
// We return the pointer
int **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i, **table;
table = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(int) );
return table;
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int main(void)
{
const int LENGTH = 1000000;
int **p;
p = get(LENGTH, 4);
printf("ok\n");
free2Darray(p ,LENGTH);
printf("exiting ok\n");
return 0;
}
and it was executed normally.
I got the code from my pseudo-site.
You should not cast what malloc returns. Why?
Also notice, that since you need a dynamic allocation only for the number of rows, since you know the number of columns. So, you can modify the code yourself (so that you have some fun too. :) )
I hope you didn't forget to **free** your memory.
I'm creating a pointer to a pointer to a structure to create a dynamic array with malloc in C, but I get a segmentation fault calling the struct array. Here is a quick rundown of my code:
#include <stdio.h>
typedef struct {
int test1;
int test2;
}testStruct;
int main() {
testStruct **neato;
neato = (testStruct **) malloc( sizeof(testStruct *) * 5);
// Array of 5 for convience
// any neato[x]->testy call results in segmentation fault.
scanf("%d", &neato[0]->test1); // Segmentation fault
return 0;
}
I tried other calls like (*neato)[0].test1 and all result in segmentation fault. This is obviously not the proper way to do this or my GNU compiler is seriously outdated.
You've allocated enough memory for 5 pointers. You have not however initialized the pointers, so they are garbage. Allocate the pointers and then proceed to initialize each pointer.
int elems = 5;
neato = malloc(sizeof(testStruct *) * elems);
for( i = 0; i < elems; ++i ) {
neato[i] = malloc(sizeof(testStruct));
}
On a side note, I don't see a need for an array of pointers here. Why not simply allocate enough space for 5 testStructs (i.e., neato becomes a testStruct*) and pass the address of that pointer to the function that initializes it?
you aren't mallocing space for all the structures themselves you have to add
for(int i = 0; i < 5; i++) {
neato[i] = malloc(sizeof(testStruct));
}
After you malloc neato. Also you should check your return value from malloc for NULL to make sure malloc passed.
You allocated array of pointers, but did not assign valid address to these pointers.
If you only want to create dynamic array, use just pointer to the struct:
testStruct *neato;
neato = malloc( sizeof(testStruct) * 5);
scanf("%d", &neato[0].test1);
I'm not very good at C yet so I have some questions.
I have two of the following structs:
typedef struct line_elems line;
typedef struct cache_handler *cache;
struct line_elems { // we don't care about valid/block bits in our simulator
int tag;
int freq; // for LRU principle
};
struct cache_handler {
int hit;
int miss;
int evict;
line **lines; // 2d array for sets
};
In initialized the cache by:
cache make_cache(int s, int E) {
int i;
cache new = malloc(sizeof(struct cache_handler));
new->hit = 0;
new->miss = 0;
new->evict = 0;
line **new_line = malloc((1 << s) * sizeof(*new_line));
for(i = 0; i < (1 << s); i++)
new_line[i] = malloc(E * sizeof(struct line_elems));
new->lines = new_line;
return new;
}
Now, I want to create a system to search through a single row in the 2d array:
int search_lines(line *lines, int E, int tag, int frequency) {
int i;
for(i = 0; i < E; i++) {
//continue here
}
}
I'm a little confused on what exactly I'm supposed to input into my search_lines function.
If I input: search_lines(cache->lines[0], E=5, tag=5, frequency=5) Will it do what I'm expecting? That is, will it search through a single line in my 2d array? I feel that cache->lines[0] is not the same as a (line*).
What is the difference between a cache->lines and a cache->lines[0]? This is confusing me because does the -> operator implicitly perform one level of dereferencing?
Thank you.
"What is the difference between a cache->lines and a cache->lines[0]?"
cache->lines is struct line_elems** which is your 2D array. Actually it is a pointer to first element of your 2D array. Operator -> is used because cache is cache_handler* = you are accessing members of struct cache_handler with it.
cache->lines[0] is struct line_elems* which is 1D array at index 0 = it is also a pointer to first element of your 2D array.
Note that freeing of this memory should have opposite order than your allocation:
line **new_line = malloc((1 << s) * sizeof(*new_line));
for(i = 0; i < (1 << s); i++)
new_line[i] = malloc(E * sizeof(struct line_elems));
you free each new_line[i] first and after that you free new_line itself:
for(i = 0; i < (1 << s); i++)
free(new_line[i]);
free(new_line);
The -> operator is not dereferencing lines, it is dereferencing cache. This is necessary because cache is also a pointer (created by a call to malloc.) Thus, it must be dereferenced before accessing any of its fields.
cache->lines is a line **
cache->lines[0] is a line *
Yes, the reference of cache->lines[0] does indeed return a pointer to your allocated array of 'lines', and thus yes your example call is in fact the right way to do it.
Remember that the cache->lines is a allocated array of pointers (the second call to malloc). It merely allocates enough space for 2^s * the_size_of_a_pointer
The rest of the mallocs below that allocate enough space for E * size_of_a_line.
So when you dereference the cache pointer (using ->) and then deference the lines pointer (by using [0]) then you end up with a memory pointer to E lines.
Then in your function, you can use lines[0] to get to the first line, and lines[E-1] to get to the last of whatever array of line pointers was passed in (based on the [] operator to the cache->lines data pointer).