Accessing allocated memory without a segmentation fault - c

I am trying to make a char matrix for a tic tak toe game. I allocated memory for it but I can't access it. It shows me a segmentation fault and I can't seem to figure out why.
#include <stdio.h>
#include <stdlib.h>
//function to make a char matrix
void make_board (char** board)
{
board = malloc(sizeof(char*)*3);
for(int i=0;i<3;i++)
{
board[i] = malloc(sizeof(char)*3);
}
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
board[i][j]='x';
}
}
}
//main function
int main ()
{
char ** board;
make_board(board);
/*when i try to access it it show me a segmentation fault*/
printf("%c\n",**board);
}

The reason your code is throwing a segmentation fault is related to the way in which you are passing a pointer to an array of chars into your function. In make_board, by reassigning the variable board with malloc you are telling the computer, "Make board point to an array of characters." This sounds like it would work, but when you do this you are only re-assigning the variable board within make_board. In main, the variable board remains untouched since variables are copied into functions in c, rather than passed in with the ability to edit. The other problem with your code is that you never initialize the variable board before you pass it into make_board, so you are passing in 0x0, or as interpreted by the computer, nothing.
To help you understand, this is a play by play of what the computer does in this program (keep in mind, this assumes that you add a line that allocates board in main):
Step 1: (Entering main) The user wants a char** named board. I will allocate it so that it points to the address 0x1234123412341234.
Step 2: Ok, now I should pass board into make_board. (keep in mind, it passes 0x1234123412341234 and nothing else).
Step 3: (Entering make_board) Ok, the user wants to allocate board to 3 char* types, so I will assign board to 0x1234567812345678.
This is where things have gone wrong. The rest of your code works, but when you enter main again, board is still 0x1234123412341234 rather than the value of 0x1234567812345678. This way, when you go to print **board, it has never been assigned and points to nothing, throwing a segmentation fault.
Here is my code that fixes this by passing in a char***, board_ptr, which allows make_board to create a char** pointed to by its parameter without changing it.
#include <stdio.h>
#include <stdlib.h>
//function to make a char matrix
void make_board(char*** board_ptr)
{
*board_ptr = calloc(3, sizeof(char*));
char **board = *board_ptr;
for (int i = 0; i < 3; i++) {
board[i] = calloc(3, sizeof(char));
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j]='x';
}
}
}
//main function
int main(int argc, char *argv[])
{
char ***board_ptr = calloc(1, sizeof(char**));
char **board;
make_board(board_ptr);
board = *board_ptr;
printf("%c\n", **board);/* Now it works! */
}

You change board variable inside make_board, but you pass it by value, so it is not changed in the main function. You try to printf the board variable, which was initialized with garbage, thus you received segmentation fault. You should return pointer from make_board: char **board = make_board() . Or pass board variable by pointer:make_board(&board)

Related

Double Dynamic Array

This is my first time working with dynamic arrays and I am honestly just so confused. My original array(below) works fine.
#include <stdio.h>
int main()
{
char icdC[4][10];
for(int i =0;i<4;i++){
for(int j=0;j<10;j++){
printf("What are your ICD codes [%d][%d]\n",i,j);
scanf("%s", &icdC[i][j]);
}
}
return 0;
}
However I tried converting this array into a double dynamic array (below) it doesn't seem to work correctly as it will either tell me "signal: segmentation fault (core dumped) or it just won't run.
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
int main()
{
char** icdC;
icdC = (char**)malloc(4*10*sizeof(char));
for(int i=0;i<4;i++){
for(int j=0;j<10;j++){
printf("What are your ICD codes [%d][%d]\n",i,j);
scanf("%s", &icdC[i][j]);
}
}
return 0;
}
The issue seems to be located within icdC = (char**)malloc(4*10*sizeof(char));, as it is an incorrect reference to the second array you're trying to create.
In C there are many options to represent a 2d array, among which the possibility to
create an array of pointers, each of which points to a specific row. Then you can allocate the memory for each array using the malloc, which allows you to generate an "array of pointers".
The implementation would most likely be:
char ** icdC;
int r = 4, c = 10;
icdC = (char*) malloc(sizeof(char*) * r);
for (int i = 0; i < r; i++) {
icdC[i] = malloc(sizeof(char) * c);
}
Note: You can also do this implementation in two loops as you did above.
From here you can do a nested loop to scan the value like you've already done in your snippet. Remember that now you can access a value by indicating the index for the corresponding row and column, like this: icdC[row_num][row_column] = .....
It might look strange at the beginning, but after you get a grasp of the concept, it's all good and fun!

Segfaults and referencing struct arrays

I've got a project that involves creating a text game. I'm creating a struct for each player and putting them in an array. I'm then trying to pass in data and then pass by pointer the array to other functions, however I keep on getting segmentation faults (Although on the odd occasion working fine). I've summarised below.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char name[9];
int cardsHeld;
int hand[8];
} Player;
void printNames(Player** playerArray)
{
for (int i = 0; i < 3; i++)
{
fprintf(stdout, "%s\n", playerArray[i]->name);
}
}
void gamesetup()
{
int count;
fprintf(stdout, "How many players will be partaking in 'The Game'? ( 1 - 5)\n");
fscanf(stdin, "%d", &count);
Player** playerArray = (Player**)malloc(sizeof(Player*) * count);
for(int i = 0; i < count; i++)
{
playerArray[i] = (Player*) malloc(sizeof(Player));
fprintf(stdout, "Please enter the name for player %d.\n\n", i + 1);
fscanf(stdin, "%s", playerArray[i]->name);
}
printNames(playerArray);
}
int main(int argc, char** argv)
{
gamesetup();
return 0;
}
My questions are;
Is the fscanf getting the address of the Player.name member? I'm getting confused whether the -> operator should deference the value of the struct member or since its in an array the address?
I'm not sure why it works sometimes but not others. If it works sometimes fundamentally it should be ok. Is the malloc function allocating memory it should not or is the fscanf putting data in the wrong place.
Thank you.
-EDIT-
Changed the code so it is in a complete program that appears to work without seg faults. I think that my issues arise from not freeing the memory before termination is messing it up next time I run it without compiling first. I'm still not sure why fscanf works as in my mind the argument playerArray[i]->name is returning the value, not the address.
I've worked it out where I was confused. Thank you for all your help in the comments.
The member I am accessing in my array is a string of chars so the first member is a pointer. By using fscanf(stdin, "%s",playerArray[i]->name); This deferenced the pointer (an address) so it works. I was getting in a muddle as it was an member of an array of structs. The segfaults were caused by me messing with the code to try and fix what already worked.

Initializing array of structs strange behavior

I am using an array of structs and then set up the elements like the following:
#include <stdio.h>
#include <stdlib.h>
typedef struct _point {
char s;
unsigned int x;
unsigned int y;
} point;
point* vehicle;
int main(int argc, char *argv[]) {
/* 26 Vehicles */
vehicle = malloc(26*sizeof(point*));
for (int i = 0; i < 26; i++) {
vehicle[i].s = ' ';
}
/* Print already existing vehicles */
for (int i = 0; i < 26; i++) {
if (vehicle[i].s != ' ') {
printf("%c: x=%d y=%d\n", vehicle[i].s, vehicle[i].x, vehicle[i].y);
}
}
return 0;
}
NOTE: this is not the actual code (which is too big to post) but the set up of the array and structs is the same.
As you can see, I set every vehicle[i].s to the space character, but the loop prints the following (not it this example code but in my actual code):
: x=32215344 y=0
P: x=0 y=33
: x=2105376 y=0
Question: how can it be that after the first loop, some elements are modified in the "background" without assigning them in the code? Or can some other malloc operations overwrite/reallocate the memory?
The problem, as I see it is in
vehicle = malloc(26*sizeof(point*));
you're allocating memory for the pointer-to-the-data-type type, whereas you should be allocating for the data type itself.
To elaborate, you want to allocate memory for 26 elements of type point (i.e., struct _point), not 26 point *.
Change
vehicle = malloc(26*sizeof(point));
or, for better,
vehicle = malloc(26*sizeof * vehicle);
Otherwise, you're running short of allocated memory when you try to dererference the pointer to access ns of instances. So, you end up accessing out-of-bound memory which causes undefined behavior.
That said, just an advice, if you know the size to be allocated beforehand, (26, for example), don't use dynamic memory, there's no need for it. Use an array.

Segmentation Fault When Assigning Values to dynamic two dimensional array in C

Hi I am writing a program in C, however I am getting a segmentation fault upon running my program.
I am using gcc to compile and no warnings or errors are given at compilation time.
I tried using gdb to trace the origin of the segfault and it directs me to the line where I am assigning data values to my two dimensional array:
array[row][column] = datavalue;
When I run my program stores 3 data values and then seg faults. It should store data on 424 rows by 117 columns, but consistently it seg faults after only storing 3 data values.
My code is as follows (with some details left out):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void allmem(float** fpdata,...); // allocate memory header
void stored(float** fpdata,...); // store data header
void countnumber(int* num1, int*num2,...); // count header
int main() // main() function
{
int numberofrows = 424; // number of rows
float** fpdata; // two dimensional array fpdata of floats
allmem(fpdata,...); // call allocate memory function
stored(fpdata,...); // call function to store data
...
return 0;
} // main ()
// --------------stored() function---------------
void stored(float** fpreal,...) {
FILE *fp; // file pointer
float datavalue; // variable to hold data values read
int row;
int column;
fp = fopen("c:/file.txt","r");
for(column = 0; column < 117; column++) {
for(row = 0; row < 424; row++) {
fscanf(fp, "%f,", &datavalue);
fpdata[row][column] = datavalue;
} // for
} // for
fclose(fp);
} // stored()
// ----------allmem() function----------------
// function to allocate memory for two dimensional arrays
// I have hard coded the values of the array sizes in, but
// in my actual program they are calculated at run time based
// on the size of some input files and this is done in the
// countnumber() function
void allmem(float** fpdata,...) {
int i = 0;
fpdata = (float**) malloc((424)*sizeof(float*));
fpdata2 = (float**) malloc((424)*sizeof(float*));
...
for (i = 0; i<424; i++) {
fpdata[i] = (float*) malloc((117)*sizeof(float));
fpdata2[i] = (float*) malloc((117)*sizeof(float));
} // for
} // allmem()
fpdata is passed by value instead of by pointer or by reference. That means that when the function returns from allmem, fpdata still points to the same thing it did before and the allocated memory is lost.
You'll want to call allmem(&fpdata,...);
And use a function signature of void allmem(float*** fpdata,...)
Then, in allmem, set *fpdata = (float**)...
And, of course, (*fpdata)[i] = (float*) malloc... inside the 'for' loop.
Edit:
I expect you'd do the same for fpdata2. But you shouldn't have to change anything in stored() (although it looks like you pass in fpreal but assign values to fpdata which is probably just a simplified code error?). The pointers passed to stored should be valid as they are. You're not trying to change the pointer in stored, just values in the memory that it points to.

Array of pointers to struct, only SIGSEGVs while debugging

The following code causes a SIGSEGV, but only while debugging.
#include <stdio.h>
#include <stdlib.h>
typedef struct enemy_desc
{
int type;
int x;
int y;
}enemy;
int main()
{
enemy **enemies;
enemies=(enemy **)malloc(sizeof(enemy *)*16);
enemies[0]->type=23;
printf("%i",enemies[0]->type);
return 0;
}
You are only creating space for 16 pointers to enemy, but are not creating the actual enemy objects that you're attempting to use.
Here is an example where I create an enemy object to the first pointer in the array.
#include <iostream>
typedef struct enemy_desc
{
int type;
int x;
int y;
}enemy;
using namespace std;
int main(int argc, char **argv)
{
enemy **enemies;
enemies=(enemy **)malloc(sizeof(enemy *)*16);
memset(enemies, 0, sizeof(enemy*)*16);
enemies[0] = (enemy *) malloc(sizeof(enemy));
memset(enemies[0], 0, sizeof(enemy));
enemies[0]->type=23;
printf("type: %i x: %i y: %i\n\n",enemies[0]->type, enemies[0]->x, enemies[0]->y);
enemies[0]->x = 10;
enemies[0]->y = 25;
enemies[0]->type= 7;
printf("type: %i x: %i y: %i\n\n",enemies[0]->type, enemies[0]->x, enemies[0]->y);
free(enemies[0]);
free(enemies);
return 0;
}
You have allocated memory for 16 enemy * pointers, but you have not allocated room for the 16 enemy structs themselves. There are two ways to fix this. One is to add a loop that allocates each of the 16 enemy structs one by one:
int main()
{
enemy **enemies;
int i;
enemies = (enemy **) malloc(sizeof(enemy *) * 16);
for (i = 0; i < 16; ++i) {
enemies[i] = (enemy *) malloc(sizeof(enemy));
}
enemies[0]->type = 23;
printf("%i",enemies[0]->type);
return 0;
}
The other is to remove one level of indirection. If you declare enemy *enemies then you can allocate the 16 structs at once and forgo a loop. If there's no need for the double indirection this would be my preferred solution:
int main()
{
enemy *enemies;
enemies = (enemy *) malloc(sizeof(enemy) * 16);
enemies[0].type=23;
printf("%i",enemies[0].type);
return 0;
}
Notice that the -> operator switches to ..
You need to create the struct that the pointers point to. The reason why it only gives a SEGV while debugging will be that there's some initialisation done during debugging to cause this sort of thing to segfault; whatever random data's in enemies[0] when you're not debugging is getting dereferenced and is just happening not to cause a segfault.
Your code probably wants to read like this:
int main()
{
enemy *enemies;
enemies=(enemy *)malloc(sizeof(enemy)*16);
enemies[0].type=23;
printf("%i",enemies[0].type);
return 0;
}
Well it should crash right away... because you initialize the array of (array of pointers). And then you DEREFERENCE the first item (enemies[0]) which should give you any random pointer. You try to access that random memory area to write in the value 23.
It should be along the lines of this:
enemies = (enemy **)malloc(sizeof(enemy *) * 16);
for (int i = 0; i < 16; i++) {
enemies[i] = (enemy *)malloc(sizof(enemy));
}
... before you access it.
Looks like you want to allocate an array of pointer to struct, but you're trying to access the struct without allocating space for them. You should do:
enemy **enemies;
enemies=(enemy **)malloc(sizeof(enemy *)*16);
for(i=0;i<16;i++) // allocate space for the structs
enemies[i] = (enemy *)malloc(sizeof(enemy))
enemies[0]->type=23; // now access type field of the first struct obj in array.
On my system (x86, Debian GNU/Linux), the code always segfaults.
Crash backtrace:
signal SIGSEGV, Segmentation fault.
0x08048413 in main () at en.c:16
16 enemies[0]->type=23;
(gdb)
The assignment cited (enemies[0]->type=23;) is the problem. You only allocate memory for the array enemies, which is an array of pointers. You then access the structure that enemies[0] is supposed to point to, but you have not allocated memory for the structure, and enemies[0] is an uninitialized pointer, hence the segfault.
In cases like this, a debugger is your friend :-).

Resources