I am trying to know how the array in c is working. so i was implementing some basic array concepts. when i run the program i got the exact output but at the end of the output it says segmentation fault.
int main(void)
{
int a[] = {};
printf("Enter the number:");
int n = get_int();
int m = 0;
for(int i = 0; i<n; i++)
{
printf("insert:");
m = get_int();
a[i] = m;
}
for(int j = 0; j < n; j++)
{
printf("%d\n", a[j]);
}
}
output:
Enter the number:3
insert:1
insert:2
insert:3
1
2
3
~/workspace/ $ ./arr_test
Enter the number:5
insert:1
insert:2
insert:3
insert:4
insert:5
1
2
3
4
5
Segmentation fault
see for the first output it has a size of 3 it doesn't show segmentation fault but for second one it has a size of 5 it shows. so why its happening and what mistake i made.
You need to allocate memory for the array. Something like:
int main(void) {
int *a;
...
int n = get_int();
...
a = malloc(n * sizeof(int));
if (!a) {
// Add error handling here
}
...
}
If you know the size of the array you want to make ahead of time, declare it like int a[128]; instead of just int a[]; so a at indices 0 to 127 will be safe to write to (and subsequently read from).
If you want to declare an array of size n at runtime, use int a[] = malloc(n * sizeof(int)); or int *a = malloc(n * sizeof(int));. Make sure a is not NULL before using it, and remember to call free(a); when you are done with it to avoid a memory leak.
Related
I've a problem about deallocating memory using free() in C.
My program generates a random genealogic tree using a matrix. This matrix can be very huge depending on the number of family members. The program seemed to work fine until I decided to generate more than one tree. I noticed that generating about 100 trees causes my 8GB RAM to fill! I'm sure I can make a better code to reduce the demand of memory, but my problem remains.
I use free() to deallocate memory and there's no error. I installed Valgrind to se what's happening and it says that about 100 million byte per tree are definitely lost. This means that free() doesn't work fine. I don't now where is the problem. I link some functions that I think are correlated to the problem.
typedef struct{
int f_id;
char f_name[L_NAMES];
int generations;
int n_members;
type_people *members;
int_mtx *mtx;
}type_family;
The struct above is for the family.
typedef struct temp{
int p_id;
char name[L_NAMES];
char f_name[L_NAMES];
int generation;
int n_sons;
struct temp **sons;
int f_id;
int sex;
int age;
}type_people;
This is for the members.
typedef struct{
int i;
int j;
int **val;
}int_mtx;
And the matrix.
In the main i call the function to initialize the tree:
type_family *family_a;
family_a = malloc(sizeof(type_family));
family_a = init_family_n_gen(family_a, 6);
This is the frist part of init_family_n_gen():
type_family *init_family_n_gen(type_family *family, int n){
...
family->members = malloc(max_people * sizeof(type_people));
family->mtx = mtxcalloc(family->mtx, max_people, max_people - 1);
...
This code is for mtxcalloc that initializes the matrix:
int_mtx *mtxcalloc(int_mtx *mtx, int i, int j){
mtx = malloc(sizeof(int_mtx));
mtx->i = i;
mtx->j = j;
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
return mtx;
}
And to conclude the code to deallocate the family:
void free_family(type_family *family){
for(int m = 0; m < family->n_members; m++){
if(family->members[m].n_sons != 0){
free(family->members[m].sons);
}
}
mtxfree(family->mtx);
free(family->members);
}
And the one to deallocate the matrix:
void mtxfree(int_mtx *mtx){
for(int i = 0; i < mtx->i; i++){
free(mtx->val[i]);
}
free(mtx->val);
free(mtx);
}
Screen capture of Valgrind output
So I call the free_family(family_a) every time i need to regenerate the family but the memory still increases. (In the photo above the number of byte become 1 billion if i regenerate the family for 50 times).
Thanks for the support!
EDITED
I made a minimal reproducible example that emulates my original code. The structs and variables are the same but I changed the functions according to Weather Vane: they are all void and I pass them the double **.
The init_family_n_gen becomes:
void init_family(type_family **f){
type_family *family = malloc(sizeof(type_family));
family->members = malloc(100 * sizeof(type_people));
for(int m = 0; m < 100; m++){
family->members[m].n_sons = 0;
}
mtxcalloc(&family->mtx, 100, 99);
family->mtx->val[0][1] = 7;
family->mtx->val[9][8] = 1;
mtxrealloc(&family->mtx, 5, 4);
*f = family;
}
The main is:
type_family *family_a;
init_family(&family_a);
free_family(&family_a);
The only thing I added is this function(Is the code right?):
void mtxrealloc(int_mtx **mtx, int i, int j){
(*mtx)->i = i;
(*mtx)->j = j;
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
for(int a = 0; a < (*mtx)->i; a++){
(*mtx)->val[a] = realloc((*mtx)->val[a], (*mtx)->j * sizeof(int));
}
}
I noticed that the problem occours when i use the realloc function and i can't figure why. I link the images of Valgrind with and without the function mtxrealloc. (I see that there is aslo a 48 byte leak...).
Valgrind with realloc
Valgrind without realloc
Thanks again for your support!
This:
init_family(&family_a);
Causes this code from mtxcalloc to execute:
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
, with i, j = 100, 99. That is, you allocate space for 100 pointers, and for each one, you allocate space for 99 ints. These are then accessible via family_a->mtx.
Very shortly thereafter, you make this call:
mtxrealloc(&family->mtx, 5, 4);
, which does this, among other things:
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
That loses all the pointers (*mtx)->val[5] through (*mtx)->val[99], each of which is the sole pointer to allocated space sufficient for 99 ints. Overall, sufficient space for 9405 ints is leaked before you even perform any computations with the object you are preparing.
It is unclear why you overallocate, just to immediately (attempt to) free the excess, but perhaps that's an artifact of your code simplification. It would be much better to come up with a way to determine how much space you need in advance, and then allocate only that much in the first place. But if you do need to reallocate this particular data, then you need to first free each of the (*mtx)->val[x] that will be lost. Of course, if you were going to reallocate larger, then you would need to allocate / reallocate all of the (*mtx)->val[x].
This program is supposed to allow the user to type in as many variables as they would like (which is stored in an array). Once the user types in "-999", the program will stop filling the array, find the largest number in the array and end. However, when I input some test numbers into the program, it will successfully end at times, but other times it will just decide to crash.
For example, I could type in:
100 (return) 200 (return) 300 (return) 400 (return) -999 (return)
and it will crash.
Then I'll type in:
10 (return) 20 (return) 30 (return) 40 (return) -999 (return)
and it will run successfully. Then if I type what I typed originally it will work and won't crash. And I'll even repeat this test and it won't replicate the same results.
I'm totally confused and lost, any help would be appreciated.
#include <stdio.h>
void fillArray(int *a);
int largestElement(int *a);
int i = 0;
int main()
{
int *array = (int *)malloc(sizeof(int));
fillArray(array);
printf("The largest element in 'array' is: %d\n", largestElement(array));
//Program randomly crashes right here sometimes, not sure why.
printf("Right before free function...\n");
free(array);
printf("Successfully freed!\n");
return 0;
}
void fillArray (int *a)
{
int userInput = 0;
printf("Type in a list of numbers terminated by a -999:\n");
while(userInput != -999)
{
//*a = realloc(a, (i+1) * sizeof(int));
scanf("%d", &userInput);
a[i] = userInput;
i++;
}
}
int largestElement(int *a)
{
int j;
int largest = a[0];
for(j = 0; j < i; j++){
if(a[j] > largest){
largest = a[j];
}
}
return largest;
}
The reason for the crash on free is because you only allocate space for a single int, but you copy values into a as if it's an array with multiple values. Writing past the end of allocated memory like that invokes undefined behavior.
The call to realloc you have commented out isn't quite doing what you want:
*a = realloc(a, (i+1) * sizeof(int));
The expression *a is of type int, do it doesn't make sense to assign a pointer back to it. Because realloc can move the memory that was originally allocated, you need to pass the address of array in main so that it can be modified in the calling function.
So change fillArray to take a pointer-to-pointer:
void fillArray (int **a)
{
int userInput = 0;
printf("Type in a list of numbers terminated by a -999:\n");
while(userInput != -999)
{
*a = realloc(*a, (i+1) * sizeof(int));
scanf("%d", &userInput);
(*a)[i] = userInput;
i++;
}
}
And call it like this:
fillArray(&array);
I'm trying to code a function that would ask the user to enter matrix. It prompts the number of lines, the number of columns and then prompts the value for each element of the matrix:
#include <stdio.h>
#include <stdlib.h>
void enterMatrix(float ** matrix, int nbLines, int nbColumns){
for (int i = 0; i < nbLines * nbColumns; i++){
printf("i = %d? ", i);
scanf("%f", matrix[i]);
}
}
int main(void){
int nbLines, nbColumns;
printf("nbLines? "); scanf("%d", &nbLines);
printf("nbColumns? "); scanf("%d", &nbColumns);
float *matrix[nbL * nbCol];
enterMatrix(matrix, nbLines, nbColumns);
}
Everything works fine until I enter a value for i = 0 and then press enter, which leads to a segmentation fault.
Any idea as to what could be wrong?
Your problem is because
float *matrice[nbL * nbCol];
defines an array of uninitialised pointers (i.e. an array of float *), not an array of float. This is then passed to enterMatrix() as a pointer to pointer to float (i.e. a float **). The scanf() calls then read to matrix[i] which is an uninitialised pointer. The result is undefined behaviour.
One fix would be to change the definition of matrice in main() to
float matrice[nbL * nbCol];
and change the function to (I've used comment to highlight changes)
void enterMatrix(float *matrix, int nbLines, int nbColumns) /* note type of matrix */
{
for (int i = 0; i < nbLines * nbColumns; i++)
{
printf("i = %d? ", i);
scanf("%f", &matrix[i]); /* note what the second argument is */
}
}
You need to allocate memory dinamically since you do not know at compile time which values the variables nbLines and nbColumns will hold.
So you need to first declare the pointer to the matrix:
float **matrix;
Then start allocate memory according to user input:
matrix = (float **)malloc(nbLines * sizeof(float *));
for (int i = 0; i < nbLines; i++)
{
matrix[i] = (float *)malloc(nbColums * sizeof(float ));
}
The segmentation fault error happens becouse you are not allocating memory for your matrix, but just a [nbL * nbCol] pointers to float
You don't allocate enough memory for your array, thus you invoke Undefined Behavior, since you go out of bounds, causing a Segmentation fault.
You could declare it like a 2D array, like this:
/* TODO: Check if allocation succeeded. (check for NULL pointer) */
float** matrix;
matrix = malloc(nbLines * sizeof(float*));
for(int i = 0 ; i < N ; i++)
matrix[i] = malloc(nbColumns * sizeof(float));
I have other approaches for allocating a 2D array dynamically here.
Please note: Do I cast the result of malloc? No!
Also do not forget to free().
You could emulate a 2D array with an 1D array, like this:
void enterMatrix(float* matrix, int nbLines, int nbColumns){
for (int i = 0; i < nbLines ; i++) {
for (int j = 0; j < nbColumns; j++) {
scanf("%f", matrix[i + nbColumns * j]);
}
}
float matrix[nbLines * nbColumns];
You're creating a variable length array, and, of pointers.
While other answers are perfectly valid, if you really want a 2D array, you just need to change the declaration:
float matrix[nbLines][nbColumns];
to declare a 2D variable length array of floats.
Now the hard point is to pass this VLA to a function and preserve dimensions.
For that you could use C99 way of passing VLAs (note that dimensions must be located before the VLA itself). Reference: Passing a multidimensional variable length array to a function:
void enterMatrix(int nbLines, int nbColumns, float matrix[][nbColumns] ){
for (int i = 0; i < nbLines; i++){
for (int j = 0; j < nbColumns; j++)
{
scanf("%f", &matrix[i][j]);
}
}
}
call as follows:
enterMatrix(nbLines, nbColumns, matrix);
This code Giving a segmentation fault. On debugging by GDB it is giving this error:
"Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a6dde5 in _IO_vfscanf_internal (s=,
format=, argptr=argptr#entry=0x7fffffffdba8,
errp=errp#entry=0x0) at vfscanf.c:1902 1902 vfscanf.c: No such file or directory. "
void readData()
{
int **arr,m;
scanf("%d",&m);
arr = (int **)malloc(sizeof(int)*m);
for(int i=0;i<m;i++)
{
arr[i] = (int *)malloc(sizeof(int) * 2);
}
for(int i=0;i<m;i++)
{
printf("..%d ..\n",i); // if m = 20 then running only 12 times
scanf("%d %d",&arr[i][0],&arr[i][1]);
}
}
int main()
{
readData();
}
If m=20 then, Second loop is only running 12 times and then giving segmentation fault. While first loop is running 20 times.
Please Help me out.
arr = (int **)malloc(sizeof(int)*m);
This should be
arr = malloc(sizeof(int*)*m);
since you need to allocate m pointers, not m ints. Or better,
arr = malloc(sizeof(*arr)*m);
(By the way, don't cast the result of malloc.)
Following line has a problem
arr = (int **)malloc(sizeof(int)*m);
you are allocating sizeof(int) times m, this should be changed to sizeof(int *)*m to hold addresses rather than int (these might be of different sizes and can cause problem). So this should be as below
scanf("%d",&m);
arr = (int **)malloc(sizeof(int *)*m);
for(int i=0;i<m;i++)
#include <stdio.h>
void spiral(int a[10][10]) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int a[r][c];
for (i = 0; i < r; i++)
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
spiral(a);
return 0;
}
When I give a 3 x 6 array
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
The output is 14, while it should be 10
How to fix this issue?
If you enter 3 and 6 for r and c (respectively) then the type of a is not int[10][10] (or int(*)[10] as the spiral argument really is), it's int[3][6]. The memory layout is completely different for the arrays, leading to undefined behavior.
You can solve this by passing the size along to the function, and using it in the declaration of the array:
void spiral(const size_t r, const size_t c, int (*a)[c]) { ... }
Call it like expected:
spiral(r, c, a);
As noted using int a[r][c] as argument might be easier to read and understand, but it gives a false impression that a is actually an array. It's not. The compiler treats the argument as a pointer to an array of c integers, i.e. int (*a)[c].
This makes me a little conflicted... On the one hand I'm all for making things easier to read and understand (which means it will be easier to maintain), on the other hand newbies often get it wrong and think that one can pass an array intact when in fact it decays to a pointer which can lead to misunderstandings.
A few things are wrong: in void spiral() you ask for a 2D-array of 10*10, but you do not give that. Keep that part as a variable, so only ask the type you receive and not what you want to receive and with creating a dynamic array you should always do that with malloc or calloc and free them afterwards. This might be a bit hard at first, but when you start creating bigger programs this is a must if you have a question or do not understand the pointers in the program called (*) then ask me:
#include <stdio.h>
#include <stdlib.h>
void spiral(int **a) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int **a = malloc(r * sizeof(int*));
for (i = 0; i < r; i++) {
a[i] = malloc(c * sizeof(int));
}
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
}
spiral(a);
for (i = 0; i < r; i++) {
free(a[i]);
}
free(a);
return 0;
}