I have a function that looks through a number of matches from an array and find all teams in matches, that meet some conditions. When found they need to be assigned to a new array. The new array should be used as an output parameter.
I get segmentation fault: 11 when I call it. I have tried to debug but cannot seem to get why. Following is declared in main:
TEAM team_least_viewers;
double spectators = 99999;
solve_task_four(round, team, &team_least_viewers, &spectators);
And the function itself:
void solve_task_four(ROUND *round, TEAM *team, TEAM *team_least_viewers, double *spectators) {
int i, j, k = 0;
for(i=0; i<ROUNDS_PR_SEASON; i++) {
for(j=0; j<MATCH_PR_ROUND; j++) {
if(round[i].match[j].year == 2015) {
/* Searching for team name in team[]*/
for(k=0; k<NUMBER_OF_TEAMS; k++) {
/* If it matches */
if (round[i].match[j].home_team == team[k].name) {
team[k].spectators_home_last_year += round[i].match[j].spectators;
}
}
}
}
for(k=0; k<NUMBER_OF_TEAMS; k++) {
if(team[k].spectators_home_last_year < *spectators) {
*spectators = team[k].spectators_home_last_year;
}
}
}
}
The structs as requested:
typedef struct {
char weekday[WEEKDAY_SIZE], start_time[START_TIME_SIZE],
home_team[TEAM_SIZE], away_team[TEAM_SIZE];
double spectators;
int day, month, year, round, home_team_score, away_team_score;
} MATCH;
typedef struct {
MATCH match[MATCH_PR_ROUND];
} ROUND;
typedef struct {
char *name;
int points, matches_played,
matches_won, matches_draw, matches_lost,
matches_won_home, matches_won_away,
goals_for, goals_against, goal_difference;
double spectators_home_last_year;
} TEAM;
Any help is much appreciated.
I infer your questions is: How do I figure out what is causing the segmentation fault? If that's right, then one answer is to use a debugger. Another answer would be to add print statements throughout the code. The segfault is almost certainly one of the array indexings, like round[i] or round[i].match[j], so be sure to print the i and j values. You may be indexing past the end of an array or dereferencing a null pointer or an uninitialized pointer, so print the pointer values, like printf("round[%d] at %p\n", i, &round[i]).
SIGSEGV on several operating systems is signal 11, and is delivered to the process on a segmentation fault.
Segmentation faults occur when your program accesses memory in a way which isn't allowed, usually by attempting to dereference a null pointer or running off the end of an array.
In your program, the most likely culprits are are array indexes, round[i].match[j] and team[k]. (Another possibility would be if the spectator argument passed were not a valid location for writing, but this is unlikely in this particular case.) You may wish to insert code/run in a debugger to check whether each access is correct.
In particular, assuming that your ROUNDS_PR_SEASON &c. values are correct, it seems most likely that some round[i].match contains a null, if your round array was not fully initialized.
Related
We were shown this program in class yesterday and i have a question regarding it's output.
malloc.c:
#include <stdlib.h>
int *create_array(int);
int *create_array(int elements) {
int i,*x = (int *) malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
free(x);
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
return 0;
}
Question(s):
When i run the program, i get this as output:
1627793032
1627793104
2
3
4
However, shouldn't the first 2 elements be 0 and 1 respectively? The values printed here seem like memory addresses to me, am i right? Also, is this due to some mistake causing undefined behavior?
After free(x);, the values pointed to by x are no longer valid. The memory can be reused for some other purpose, and meanwhile the memory allocation library can use the storage as it sees fit.
So, yes, it is a mistake resulting in undefined behaviour.
The real question is why do you even expect it to work? You free x, then you return a freed pointer which is nonsense.
What is happening is the following:
Inside the function you allocate 5 spaces, x points to the first
one's address.
You write 0, 1, 2, 3, 4 in these spaces.
You free x, so all the 5 spaces are not reserved anymore.
You exit the function, doing so the 2 next free memory spaces are
used, which happen to be the ones where you wrote 0 and 1.
You print the values contained in the 5 memory areas you've already
freed, where the ones in which you wrote 0 and 1 happen to have been
reused for something else; hence the weird numbers.
As a general rule, do not attempt to read areas of memory i've freed; even worse, do not try to WRITE there.
Accessing unallocated memory leads to undefined behaviour.
Also, you don't need to declare the function in a separate row if it's going to have nothing in between; plus you don't have to cast what's returned by malloc to the type; it's a void* that by default can hold anything you throw at it. What matters is your base variable type. See here
Corrected code:
#include <stdlib.h>
int *create_array(int elements) {
int i,*x = malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
free(arr);
return 0;
}
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.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
i have a linked list of srtings that i need to sort in alphabetical order
and i am tryping to copy the strings to an array and then sort and print them in alphabetical order
void DisplayAll(k *l,p *p)
{
int i,j;
p *temp;
temp = malloc(l->num*sizeof *temp);
for (i = 0; i < l->num; i++)
{
strcpy_s(temp[i].name, 20, p->name);
p = p->next;
i++;
}
for (i = 0; i < l->num - 1; i++){
for (j = i + 1; j< l->num; j++)
{
if (strcmp(temp[i].name, temp[j].name) > 0)
{
strcpy_s(temp->name,20, temp[i].name);
strcpy_s(temp->name[i],20, temp[j].name);
strcpy_s(temp->name[j],20, temp->name);
}
}
for (i = 0; i < l->num-1; i++){
printf("%s\n", temp[i].name);
}
}
this is the k struct and the p stuct
typedef struct p
{
char name[20];
struct p* next;
}p;
typedef struct k
{
int num;
p *head;
}k;
and i getting an Error evey time i run it
There's a couple of problems with your code:
First off: This doesn't look right at all:
strcpy_s(temp->name,20, temp[i].name);
strcpy_s(temp->name[i],20, temp[j].name);
strcpy_s(temp->name[j],20, temp->name);
according to the docs:
errno_t strcpy_s(
char *strDestination,
size_t numberOfElements,
const char *strSource
);
The first and last arguments are expected to be of the type char*. You've defined struct p .name as char[20], so temp->name[i] will be of type char.
I guess you're actually trying to do something like this:
//get struct p at offset i in temp, access member "name"
strcpy_s(temp[i].name, 20, temp[j].name);
Secondly: You're allocating memory for temp, but you fail to free it once you're done (ie when your function returns). You have, in other words, a memory leak. Sure, once your program exits, the memory is almost certainly going to be freed, but if you're writing programs that have to run for extended periods of time, and functions like this are getting called several times over, your memory consumption will gradually increase, and you don't want that to happen. In short, after your last loop (where you print everything out), add this:
free(temp);
Edit
You've added the free call now, and -correctly- wrap it in an if (temp). However: if malloc had returned a NULL pointer, don't you think you should've cought that at the beginning of the function?
temp = malloc(l->num * sizeof *temp);
if (!temp)
return;//or return int to indicate error or or exit EXIT_FAILURE; or something
There's no reason for you to reach the point where you free(temp) without having successfully allocated the memory.
Third: As #Bluepixy pointed out in his comment, there's a syntax error, too: the if (strcmp(temp[i].name, temp[j].name) > 0) branch is never closed properly: you're missing a closing bracket after the third strcpy_s call.
Lastly, you're allocating enough memory to accomodate l->num structs. You initialize them in such a way that every other struct will be assigned the name member of the next struct p in a list. You're not really making sure that p->next isn't a null pointer. This could cause problems (dereferencing a null pointer). So change the first loop into something like this:
int l_num = l->num;//you'll see why
for (i = 0; i < l_num; i+=2)//increment twice if you want/need to
{
strcpy_s(temp[i].name, 20, p->name);
p = p->next;
if (p == NULL)
{
l_num = i+1;//this is as far as we ought to go in the subsequent loops
break;//or handle error in some way
}
}
After this, replace all your ;i < l->num; conditions in your loops with i < l_num or j < l_num to avoid using uninitialized string values.
Just a final tip: If you're not working on anything too time critical, it might be useful to use calloc instead of malloc, especially when dealing with strings, or use memset(temp[i]->name, 0, 20); to ensure all char[] members are indeed empty strings.
If you find yourself using a lot of str* functions (strncat, strncpy and the like), even something as simple as temp[i]->name[0] = '\0'; can make life a lot easier.
char getType()
{
typedef struct typelookup { const char *opcodebits; char instype; } typelookup;
typelookup table[] = {
{"000000",'r'},
{"000010",'j'},
{"000011",'j'},
{ NULL }
};
for (typelookup *t = table; t->opcodebits != NULL; ++t) {
if (strcmp(t->opcodebits, opcode) == 0) {
return t->instype;
}
}
return 'i';
}
I need to be able to perform a lookup based on a string. The string is contained in a static array and if the string is in the lookup table, I want to be able to return a character which will define which type of MIPS instruction the binary refers to, hence the r, j and i as return values. This code compiles ok but when it comes to running the code I always get a "segmentation error: 11". Can anybody enlighten me as to what I'm doing wrong? Been trying to fix this error for longer than I care to admit.
What is opcode? Does the char array pointed to by opcode contain a terminating zero? If not, strcmp may keep comparing beyond the end of t->opcodebits, run out of bounds, and suddenly hit a non-readable virtual address.
I apologise for my answer sounding like a lot of additional questions. :-)
i have a struct "cell" defined as
typedef struct{
int id;
terrainType terrain;
} cell;
i then make a 2d array of cells with
cell** makeCellGrid(int sizeX, int sizeY)
{
cell** theArray;
int i;
theArray = (cell**) malloc(sizeX*sizeof(cell*));
for ( i = 0; i < sizeX; i++)
{
theArray[i] = (cell*) malloc(sizeY*sizeof(cell));
}
return theArray;
}
at first i thought this was working fine but a few seg faults later i discovered that with some values (e.g. makeCellGrid(32, 87) ) it breaks.
im fairly fresh with C pointers and memory junk and was hoping some one could point me in the right direction here.
with lower number bounds i had no issue accessing it with
map[i][j].id = x;
and so on
EDIT: forgot to add, from testing, the seg fault originate from
theArray[i] = (cell*) malloc(sizeY*sizeof(cell));
The code lacks error checking for the malloc() system call.
So if the first call to malloc() failed the second one (in the loop) tries to assign memory to NULL which indeed leads to the segmentation violation your are witnessing.
You might consider modifing you code like so:
#include <stdlib.h>
typedef struct {
int id;
TerrainType terrain;
} CellType;
void freeCellGrid(CellType ** ppCells, size_t sizeX)
{
size_t i = 0;
for (; i < sizeX; ++i)
{
free(ppCells[i]);
}
free(ppCells);
}
CellType ** makeCellGrid(size_t sizeX, size_t sizeY)
{
CellType ** ppCells = malloc(sizeX * sizeof(*ppCells));
if (ppCells)
{
size_t i = 0;
for (; i < sizeX; ++i)
{
ppCells[i] = malloc(sizeY * sizeof(**ppCells));
if (NULL == ppCells[i])
{
freeCellGrid(ppCells, i);
ppCells = NULL;
break;
}
}
}
return ppCells;
}
Notes on my modifications:
Always check system calls for errors (in the case of malloc() on error NULL is returned)
Better use an unsigned type to access memory/array indicies; size_t is meant for this
In C there is no need to cast the value returned by a void * function like malloc()
Always try to initialise variables as soon as possible; un-initilaised variables very easily lead to "irrational" behaviour of the application
If working with pointers, it might be helpfull to 'code' the level of indirection into their names (I did this here by using the prefix pp to indicated that it's a 2-level indirection)
types are different from variables: One way to distinguish this is by starting type names using capitals (CellType) and variables using small letters (ppCells).
If allocating memory to a pointer and it matters that the size of the allocated memory some suits the pointer's type it's always more secure to use the (dereferenced) pointer itself as argument to the sizeof operator then some type. As the declaration of the pointer the memory is allocated to might be changed during develpment and the adjustment of the argument to malloc() will be forgotten. To cut it short: doing as I did is less error prone.
If encapsulating the dynamical creation of structures (including arrays) it is a could idea to also implement a method which de-allocates it (here: freeCellGrid()). Even better start of with coding this deallocator first, as then you have it by hand when coding the allocator's error handling (as shown for the second call to malloc()).