I'm struggling with a small amount of C code trying to get to run on a RPI2b.
The code is about creating a struct including a integer array with a dynamic size.
The struct file has to be declared as a pointer in my main function.
This is because: The bigger purpose of my program will be executing three Array iterations in parallel by the use of pthread.
As far as I know pthread needs a pointer in function call.
I don't want to change anything by using pthread (never change a winning team).
This is what my code snipping should do:
define a STEP number
declare a static int array with defined amount of STEP
declare a struct including a dynamic array
fill up the static int array
allocate memory for dynamic array
fill up dynamic array with values of static int array
print both on console
No errors while compiling with gcc!
The Problem is that when it Comes to allocate memory for the dynamic array program simply pints a "Segmentation fault" on the console.
The fun fact is: I've copied paste the whole code to Visual Studio 2017 and it works perfectly fine!
Here is my code:
#include<stdio.h>
#include<stdlib.h>
#define STEPS 50 //defined steps
typedef struct file File;
struct file {
int type;
int* array; //dynamic array
};
int main(void) {
int i = 0;
int mainarray[STEPS] = { 0 };
struct file *f = (File*)malloc(sizeof(File)); //allocate memory for struct
printf("Fill up static array\n");
for (i = 0; i <= STEPS; i++) {
mainarray[i] = i;
}
printf("static array values:\n");
for (i = 0; i <= STEPS; i++) {
printf("%d\n", mainarray[i]);
}
printf("allocate memory for dynamic array\n");
f->array = (int*)malloc(sizeof(int) * STEPS); //Here I receive my segmentation fault
if (f->array == NULL) {
printf("allocating error\n");
}
for (i = 0; i <= STEPS; i++) {
f->array[i] = 20000 * mainarray[i];
}
printf("compare of arrays\n");
for (i = 0; i <= STEPS; i++) {
printf("i:=\t%d\tMainarray:\t%d\tStructarray:\t%d\t\n", i, mainarray[i], f->array[i]);
}
free(f->array);
free(f);
}
Your problem is (see comment from Some Programmer Dude) that you go out of bounds of your array. That causes undefined behavior, in your case resulting in a seg fault.
for (i = 0; i <= STEPS; i++)
should be:
for (i = 0; i < STEPS; i++)
because STEPS-1 is the last valid array element.
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].
I have a question on a simple program that i wrote to initialize an array one element at a time, the few lines of code are below:
#include <stdio.h>
int main(void)
{
int *ptr;
int index;
for (index = 0; index < 4; index++)
{
ptr[index]=index;
printf("%d\n", ptr[index]);
}
return 0;
}
All plain and simple but when I run the program I incur in segmentation fault (core dumped) error, that to my understanding occurs when you try to write on something that is only readeable or if you have exceeded your allowed memory...
Excuse me for this probably nobbish question but I could not find a similar question on SO.
You cannot just use int *ptr and treat it as an array. You need to actually create an array and allocate space for it, by specifying the size. You can either make it as an array like in the first option, or allocate it using malloc() in the second option. I suggest the first one because it executes faster, and it seems your array is of fixed length. The second option is for applications where you do not know the array size until runtime.
#include <stdio.h>
int main(void)
{
int ptr[4]; //you need to specify array size first
int index;
for (index = 0; index < 4; index++)
{
ptr[index]=index;
printf("%d\n", ptr[index]);
}
return 0;
}
You can also use malloc() if you want to allocate it on the heap, but make sure to free() it, to free the memory, or there will be a memory leak.
#include <stdio.h>
int main(void)
{
int *ptr = malloc(4*sizeof(int));
int index;
for (index = 0; index < 4; index++)
{
ptr[index]=index;
printf("%d\n", ptr[index]);
}
free(ptr);
return 0;
}
This should solve your problem
Also you don't need a for loop to initialize populate the values of the array, in case that is what you are trying to do. You can do this:
int ptr[4] = {0, 1, 2, 3};
As stated in #ChristianGibbons comment, you just need to allocate memory for the array the address of your pointer.
#include <stdio.h>
int main(void)
{
int sizeOfArray = 4;
int *ptr = calloc(sizeOfArray, sizeof(int)); // line to fix
int index;
for (index = 0; index < sizeOfArray; index++)
{
ptr[index]=index;
printf("%d\n", ptr[index]);
}
free(ptr);
return 0;
}
When trying to input a string of chars, i get a warning
warning: 'doc' may be uninitialized in this function [-Wmaybe-uninitualized]
When i run the code, it only allows me to enter the string itself and then it stops.
I tried compiling the code using an online compiler and it returned `segmentation fault (core dumped). I know something is wrong but i don't know how to fix it.
#include <stdio.h>
#include <string.h>
typedef struct Pacient{
char ime_prezime[100];
int osiguruvanje;
int broj_pregledi;
}Pacient;
typedef struct MaticenDoktor{
char ime_prezime[100];
int broj_pacienti;
Pacient pacient[200];
float cena;
}MaticenDoktor;
void najuspesen_doktor(MaticenDoktor *doc, int n){
int i, j, najgolema_zarabotka=0, najmnogu_pregledi=0, zarabotka, pregledi;
char najuspesen[100];
for(i=0; i<n; i++){
zarabotka=0;
pregledi=0;
for(j=0; j<doc[i].broj_pacienti; j++){
if(doc[i].pacient[j].osiguruvanje==0){
zarabotka+=doc[i].cena;
pregledi++;
}
}
if(zarabotka>najgolema_zarabotka){
najgolema_zarabotka=zarabotka;
strcpy(najuspesen, doc[i].ime_prezime);
najmnogu_pregledi=pregledi;
}
else if(zarabotka==najgolema_zarabotka){
if(pregledi>najmnogu_pregledi){
najgolema_zarabotka=zarabotka;
strcpy(najuspesen, doc[i].ime_prezime);
najmnogu_pregledi=pregledi;
}
}
}
printf("%s %d %d", najuspesen, najgolema_zarabotka, najmnogu_pregledi);
}
int main()
{
int i, j, n;
printf("Vnesi broj na doktori\n");
scanf("%d", &n);
MaticenDoktor *doc;
for(i=0; i<n; i++){
scanf("%s", doc[i].ime_prezime); // <---- warning here
scanf("%d", &doc[i].broj_pacienti);
scanf("%f", &doc[i].cena);
for(j=0; j<doc[i].broj_pacienti; j++){
scanf("%s", doc[i].pacient[j].ime_prezime);
scanf("%d", &doc[i].pacient[j].osiguruvanje);
scanf("%d", &doc[i].pacient[j].broj_pregledi);
}
}
najuspesen_doktor(doc, n);
return 0;
}
Does anyone know how to fix this?
MaticenDoktor *doc; only declares a pointer, and not the full structure (or the array). You need to initialize it to point to somewhere, where you can warrant there's enough free memory to hold the information. You can ensure this in several ways:
You can, instead, hold a complete structure in the function body (main in your case, with this similar declaration:
MaticenDoktor doc; /* no pointer, but a full structure variable is declared */
scan("%s", doc.ime_prezime);
...
You can, declare an array of MaticenDoktor structures with the following code:
MaticenDoktor doc[100]; /* now doc is an array with space for 100 MaticenDoktors */
scan("%s", doc[n].ime_prezime); /* n ranges from 0 to 99 max */
You can, if you don't know a priori how many MaticenDoktor you are going to have, and you read it before the loop, with:
MaticenDoktor *doc = malloc(n * sizeof *doc); /* you have doc pointing to an array of n MaticenDoktors */
scan("%s", doc[n].ime_prezime);
...
free(doc); /* after you are completely finished using doc */
You can, if you are short of memory, just declare an array of pointers with space for the maximum, and allocate the structures as you need them:
MaticenDoktor *doc[1000]; /* space for maximum of 1000 pointers to MaticenDoktor */
for (i = 0; i < n && i < 1000; i++) {
doc[i] = malloc(sizeof *doc[i]); /* size of pointed value, not of pointer */
scanf("%s", doc[i]->ime_prezime);
...
}
and later on
for (i = 0; i < n && i < 1000; i++) {
free(doc[i]); /* free space used by doc[i] */
}
... and many other ways to organize your memory :)
doc has not been assigned so points to an unpredictable location. You should either place it on the stack:
assing dynamic memory first.
MaticenDoktor *doc;
int len = 10; // all memory that you need.
doc =(MaticenDoktor *)malloc(sizeof(MaticenDoktor)*len);
it fix the Warning .
Code:
#include <stdio.h>
int main() {
int size;
scanf("%d", &size);
int foo[size];
for(int i = 0; i < size; i++)
scanf("%d", &foo[i]);
for(int i = 0; i < size; i++)
printf("%d\n",foo[i]);
return 0;
}
How does this code compile? More specifically: how does the compiler know what is the size of frame main if size of local variable foois not known at compile time. I was expecting a compile error along the lines: "foo has incomplete type"
To have also tried the code and it also runs fine:
In your code, you will first read data to specify size of array elements and then it will allocate that array on stack.
This approach is available from C99.
How compiler knows the size? It doesn't know. if you will enter too big value for size you may get stack overflow.
It will compile in a way that it will make sure to create as big push as required to put entire array to stack according to variable of size multiplied by size of single array element:
stack_size_usage = size * sizeof (int)
In C89, this would reproduce error as all variables must be first initialized before any code can be executed.
I would instead use HEAP memory for this type of allocation.
#include <stdio.h>
int main() {
int size;
int* foo;
scanf("%d", &size);
foo = malloc(sizeof(*foo) * size);
if (!foo) { /* failed, stop program */ }
for(int i = 0; i < size; i++)
scanf("%d", &foo[i]);
for(int i = 0; i < size; i++)
printf("%d\n",foo[i]);
free(foo);
return 0;
}
I need to create a program that plays the game Hex on a 14x14 board.
So I created, allocated and filled the board with '-' (our pattern for empty spaces).
When I try to print the board's coordinates, I don't always get '-' but some random characters.
Also, if I try to printf array[i][j] on the createBoard function after the line "board[i][j] = '-';" I get a segmentation fault right after it prints tab[8][0].
What is causing this and how can I fix it?
My code:
#include <stdio.h>
#include <stdlib.h>
char **createBoard()
{
/*Allocates a 14x14 matrix and fills it
*with '-' to create the board.*/
int i, j;
char **board;
board = malloc(14);
if (!board) exit(1);
for (i = 0; i < 14; i++){
board[i] = malloc(14);
if (!board[i]) exit (1);
for (j = 0; j < 14; j++)
board[i][j] = '-';
}
return board;
}
int main()
{
int i, j;
char **board = createBoard();
for (i = 0; i < 14; i++)
for (j = 0; j < 14; j++)
printf("tab[%d][%d]: %c\n",i, j, board[i][j]);
return 0;
}
For starters it is not clear why you don't want to declare an array instead of allocating dynamically numerous one-dimensional arrays.
As for the code then this memory allocation
board = malloc(14);
is invalid. You have to write
board = malloc( 14 * sizeof( char * ));
Also you should free all the allocated memory in the reverse order relative to its allocation before the program ends.
Take into account that it is always better to use named constants instead of magic numbers. At least you could write either
#define N 14
before main
or
const int N = 14.
and use the variable N everywhere where you are using magic number 14.
By the way according to the C Standard function main without parameters shall be declared like
int main( void )
The variable *board is a pointer, but you only allocate one byte for each array element, which should be
#define DIM 14
board = malloc(DIM * sizeof *board);
Following that up with the second allocation
board[i] = malloc(DIM * sizeof **board);
This also allows (a) that the dimension 14 is hard coded in only one place in the program and (b) the allocation will survive if you later make the board's element a different type, for example a struct, as the program develops.