Segmentation Fault in a C function - c

I hope you have spent beautiful Christmas holidays. I am studying for an exam and I have a problem with my project in ANSI C. My code works but not always, it's strange because for some input values it works for other not. I have two arrays, A and B, that must be different in size and I have to write a function that do the mathematical union of the two arrays in another array. If there are elements of the same value I have to insert in the new array only one. I write all the code (I also post a question here because I had some problems with the union) but it does not work always. Gcc compile and I execute but it's not correct. I debugged with gdb and it said
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400d1c in unionearraycrescente (a=0x7fffffffdd50, indice_m=4,
b=0x7fff00000005, indice_n=5, minimo=6, indiceMinimo=22)
at array.c:152
152 if(b[i]==c[j])
And this is the code near the problem
int arrayun(int a[], int index_m, int b[], int index_n, int minimum, int indexMinimum)
{
int i=0;
int j=0;
int found;
int lenc=0;
int c[lenc];
for(i=0;i<index_m;i++){
found = 0;
for(j=0; j<i && !found;j++)
if(a[i]==c[j])
found = 1;
if(!found)
c[lenc++] = a[i];
}
for(i=0;i<index_n;i++){
found=0;
for(j=0;j<i && !found;j++)
{
if(b[i]==c[j]) //debug gbd problem - segfault
found = 1;
}
if(!found)
c[lenc++] = b[i];
}
I am Italian so the comments are in my language, if you have any problems I will translate the comments. I want only to resolve this memory error. Thank you.
I follow some of your advices and in that part of code it works, I changed all the variables with index_m and I don't receive segfault but after the union I use the selection sort to sort in ascending order and it return me not the right values but in the first position negative values.
int arrayun (int a[], int index_m, int b[], int index_n, int minimum, int indexMinimum)
{
int i=0;
int j=0;
int found;
int lenc;
int c[index_m];
for(i=0;i<index_m;i++){
found = 0;
for(j=0; j<i && !found;j++)
if(a[i]==c[j])
found = 1; //setta trovato = 1
if(!found)
c[index_m++] = a[i];
}
for(i=0;i<index_n;i++){ //index_m or index_n?
found=0;
for(j=0;j<i && !found;j++)
{
if(b[i]==c[j]) //debug gbd problem - segfault - SOLVED but
found = 1;
}
if(!found)
c[index_m++] = b[i];
}
for (i=0; i<index_m-1;i++)
{
minimum=c[i];
indexMinimum=i;
for (j=i+1;j<index_m; j++)
{
if (c[j]<minimum)
{
minimum=c[j];
indiexMinimum=j;
}
}
c[indexMinimum]=c[i];
c[i]=minimum;
}
for(i=0;i<index_m;i++)
printf("Element %d\n",c[i]);
return c[index_m]; //I think here it's wrong
}

int c[lenc]; means in your program it is c[0]
and you are allocating ZERO Memory for the array.
And if you try for b[i]==c[i] where i>=0 means its a segmentation fault only.
Instead you can initialize like,
c[index_m];

int lenc=0;
int c[lenc];
this is array of 0 length.and in loop you are trying to access c[1],c[2]... etc.
To cure this problem you can pass length of the bigger array
int unionearraycrescente (int a[], int index_m, int b[], int index_n,int len, int minimum, int indexMinimum)
and you can then initialize like
int c[len];

Related

Large array causing segmentation fault

I wrote a code with the following specified constraints:
Hence I chose the data types for my variables accordingly.
However my code fails all the test cases saying segmentation fault. (possibly because the array size they input is very large.) Is there a way to get more stack space or heap space? or get around this problem by declaring the array in some other way? Is there something else that's causing segmentation fault? Other people have solved this problem, so there must be a way.
this is the code:
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
long find_index(long x, long *cost, long n, long used_index)
{
long i;
for(i = 0; i < n; i++)
if(*(cost + i) == x && i != used_index)
return (i+1);
return 0;
}
int purchase(long *cost, long n, long money)
{
long i, index;
for(i = 0; i < n ;i++)
{
index = find_index((money - *(cost - i)),cost,n,i);
if(index)
{
printf("%ld %ld\n",i+1,index);
break;
}
}
free(cost);
return 0;
}
int main(void)
{
int t;
long *cost, money, n, i;
scanf("%d",&t);
while(t > 0)
{
scanf("%ld",&money);
scanf("%ld",&n);
cost = (long *)malloc(n*sizeof(long));
for(i = 0; i < n; i++)
scanf("%ld",(cost+i));
purchase(cost,n,money);
t--;
}
return 0;
}
this is one of the hidden test cases they check for:
35 // this is t
299701136 // this is money
2044 // this is n
50293811 136626876 58515785 59281065 ..... goes on forever...
That's a lot of complex code to analyze, so instead of giving you a fish, I'll try to give you a rod.
Whatever platform, compiler and IDE you're using, there probably is a way to perform step-by-step debugging of your program at runtime. Maybe your assumptions are wrong and the allocation size is not causing this problem.
Learning basics of debugging is really great tool in programmer's hands. Here is an example tutorial video: https://www.youtube.com/watch?v=9gAjIQc4bPU
These changes in the code fix the issue of array index out of bounds problem, Hence the segmentation fault issue:
if((money - *(cost + i)) < n)
index = find_index((money - *(cost + i)),cost,n,i);
The constraints mentioned cause no issue.

segfault when iterating over 2d array

I am trying to do a simple function which prints an array of a defined size. However, after the function prints the array, a seg fault occurs. This seg fault only occurs when boardSIZE is defined as equal to 19 or larger. Anything less then 19, and no segmentation fault occurs. Can anyone explain why this is, and/or suggest how I can perform a similar task of defining a global variable larger than 20 here without getting a seg fault?
#include <stdio.h>
#define boardSIZE 40
void printBoard(char [][boardSIZE]);
int main()
{
char board[boardSIZE][boardSIZE];
printBoard(board);
}
void printBoard(char board[boardSIZE][boardSIZE])
{
int i,j;
for (i=0;i<=boardSIZE;i++){
for (j=0;j<=boardSIZE;j++){
board[i][j]='X';
printf("%c",board[i][j]);
}
printf("\n");
}
}
Don't use <= in your loops. Use <. For an array of size n, valid indexes go from 0 to n-1. Thus, your loop is accessing out-of-bound positions.
Change your printBoard() function to:
void printBoard(char board[boardSIZE][boardSIZE])
{
int i,j;
for (i=0;i<boardSIZE;i++){
for (j=0;j<boardSIZE;j++){
board[i][j]='X';
printf("%c",board[i][j]);
}
printf("\n");
}
}
you blow the array bounds.
you allocated boardSIZE, this means the max index that is available is boardSIZE - 1 because the first index is 0 not 1. so change the <= to < in both for loops and the seg fault will resolve!
void printBoard(char board[boardSIZE][boardSIZE]) {
int i,j;
for (i = 0; i < boardSIZE; i++){
for (j = 0; j < boardSIZE; j++){
board[i][j] = 'X';
printf("%c",board[i][j]);
}
printf("\n");
}
I suggest you edit your title to something more suitable as this doesn't have anything to do with global variables

Trying to write a function to shuffle a deck in C

So all I'm trying to do is take an input from the user of how many cards to use and then randomly assign each card to a different index in an array. I'm having extensive issues getting the rand function to work properly. I've done enough reading to find multiple different ways of shuffling elements in an array to find this one to be the easiest in regards to avoiding duplicates. I'm using GCC and after I input the amount of cards I never get the values from the array back and if I do they're all obscenely large numbers. Any help would be appreciated.
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
void main(){
srand(time(NULL));
int d, c, i, z, l, r;
printf("Enter the deck length: ");
scanf("%d\n ", &c);
int deck[c];
int swap[c];
z = c;
for(l=0; l<c; l++){
swap[l] = l;
}
for(i=z; i=0; i--){
r = rand() / i
deck[i] = swap[r];
for(r; r=(c-1); r++){
swap[r] = swap[(r+1)];
}
}
for(d = 0; d < c; d++){
printf("%d ", deck[d]);
}
return;
}
I can spot one major problem here:
for(i=z; i=0; i--)
^^^
This loop will never execute since you are using assignment(=) and setting i to 0 therefore the condition will always be false, although using equality(==) will still be false in this case, you probably want:
for(i=z; i!=0; i--)
This means you will be using deck unitialized which is undefined behavior. Once you fix that you have a similar problems here:
for(r; r=(c-1); r++){
main has to return int and your return at the end needs to provide a value.
Turning on warning should have allowed you to find most of these issues, for example using -Wall with gcc gives me the following warning for both for loops:
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
Note, see How can I get random integers in a certain range? for guidelines on how to use rand properly.
You basically need to be able to generate 52 numbers pseudo-randomly, without repeating. Here is a way to do that...
First, loop a random number generator 52 times, with a method to ensure none of the random numbers repeat. Two functions in addition to the main() will help to do this:
#include <ansi_c.h>
int NotUsedRecently (int number);
int randomGenerator(int min, int max);
int main(void)
{
int i;
for(i=0;i<52;i++)
{
printf("Card %d :%d\n",i+1, randomGenerator(1, 52));
}
getchar();
return 0;
}
int randomGenerator(int min, int max)
{
int random=0, trying=0;
trying = 1;
while(trying)
{
srand(clock());
random = (rand()/32767.0)*(max+1);
((random >= min)&&(NotUsedRecently(random))) ? (trying = 0) : (trying = 1);
}
return random;
}
int NotUsedRecently (int number)
{
static int recent[1000];//make sure this index is at least > the number of values in array you are trying to fill
int i,j;
int notUsed = 1;
for(i=0;i<(sizeof(recent)/sizeof(recent[0]));i++) (number != recent[i]) ? (notUsed==notUsed) : (notUsed=0, i=(sizeof(recent)/sizeof(recent[0])));
if(notUsed)
{
for(j=(sizeof(recent)/sizeof(recent[0]));j>1;j--)
{
recent[j-1] = recent[j-2];
}
recent[j-1] = number;
}
return notUsed;
}

Kruskal C implementation

I have implemented the Kruskal algorithm in C using an adjacency matrix graph representation, the problem is, it keeps popping up segmentation fault error, I've been trying to figure out what is wrong for quite a while and I can't seem to find the problem, could anyone else take a look please?
Thanks.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define MAXVERT 10
#define MAXEDGES 20
#define INF 100000
/*graph representation using an Adjacency matrix*/
typedef struct AdjMatrix
{
int nodes;
int adjMat[MAXVERT][MAXVERT];
} graph;
/*function prototypes*/
int find(int node, int *trees);
void merge(int i, int j, int *trees);
void printminimal(int min[][3], int n);
/*main algorithm*/
void kruskal(graph *g)
{
int EDGES[MAXEDGES][3]; /*graph edges*/
int MINEDGES[MAXVERT-1][3]; /*edges already in the minimal spanning tree*/
int nextedge=0;
int numedges=0;
int trees[MAXVERT]; /*tree subsets*/
int i, j, k;
int temp;
for(i=0;i<g->nodes;i++)
trees[i]=i;
k=0;
for(i=0; i<g->nodes; i++)
for(j=0; j<g->nodes; j++)
{
if(i<j)
{
EDGES[k][0]=i;
EDGES[k][1]=j;
EDGES[k][2]=g->adjMat[i][j];
k++;
}
else
break;
}
/*Bubblesort*/
for(i=0; i<g->nodes; i++)
for(j=0; j<i; j++)
{
if(EDGES[j][2] > EDGES[j+1][2])
{
temp=EDGES[j][0];
EDGES[j][0]=EDGES[j+1][0];
EDGES[j+1][0]=temp;
temp=EDGES[j][1];
EDGES[j][1]=EDGES[j+1][1];
EDGES[j+1][1]=temp;
temp=EDGES[j][2];
EDGES[j][2]=EDGES[j+1][2];
EDGES[j+1][2]=temp;
}
}
while(numedges < (g->nodes-1))
{
i=find(EDGES[nextedge][0], trees);
j=find(EDGES[nextedge][1], trees);
if((i!=j)&&(EDGES[nextedge][2]!=-1)) /*check if the nodes belong to the same subtree*/
{
merge(i,j,trees);
MINEDGES[numedges][0]=EDGES[nextedge][0];
MINEDGES[numedges][1]=EDGES[nextedge][1];
MINEDGES[numedges][2]=EDGES[nextedge][2];
numedges++;
}
nextedge++;
}
}
int find(int node, int *trees)
{
if(trees[node]!=node)
return trees[node];
else
return node;
}
void merge(int i, int j, int *trees)
{
if(i<j)
trees[j]=i;
else
trees[i]=j;
}
void printminimal(int min[][3], int n)
{
int i, weight=0;
printf("Minimal tree:\n(");
for(i=0;i<n;i++)
{
printf("(V%d,V%d), ", min[i][0],min[i][1]);
weight+=min[i][2];
}
printf(")\n Total weight sum of the minimal tree is: %d", weight);
}
int main(void)
{
int i,j;
graph *g=(graph *)malloc(sizeof(graph));
/*int adjMat[8][8] = {0,INF,INF,11,INF,1,7,
INF,0,INF,3,INF,4,8,INF,
INF,INF,0,INF,INF,INF,12,INF,
INF,3,INF,0,15,INF,INF,INF,
11,INF,INF,INF,0,20,INF,INF,
INF,4,INF,INF,20,0,INF,INF,
1,8,12,INF,INF,INF,0,5,
7,INF,INF,INF,INF,INF,5,0};*/
for(i=0;i<4;i++)
for(j=0;j<i;j++)
{
if(i==j)
{
g->adjMat[i][j]=0;
continue;
}
printf("%d-%d= ", i, j);
scanf("%d", &(g->adjMat[i][j]));
g->adjMat[j][i]=g->adjMat[i][j];
}
g->nodes=4;
kruskal(g);
}
In the kruskal function, where you intend to populate the EDGES array, you don't:
for(i=0; i<g->nodes; i++)
for(j=0; j<g->nodes; j++)
{
if(i<j)
{
EDGES[k][0]=i;
EDGES[k][1]=j;
EDGES[k][2]=g->adjMat[i][j];
k++;
}
else
break;
}
For j == 0, i is never < j, so you immediately break out of the inner loop. I suspect it should be i > j in the condition.
Since EDGES is uninitialised, find tries to access an unspecified element of trees.
I had to add the following to get this to kruskal to get it to compile from gcc:
int *dvra = trees;
You can then compile it with debug information:
gcc -g -o kruskal kruskal.c
and run it through gdb:
gdb kruskal
You can then type run and enter to start the program. I entered 1,2,3,... when prompted for values.
This then gives:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400a92 in find (node=32767, trees=0x7fffffffe110) at test.c:86
86 if(trees[node]!=node)
Hmm, that's curious. Trees holds only 10 items (value of the MAXVERT define), so accessing node 32767 goes out of bounds. If you enter 32767 in the calculator program and go to the programming (hexadecimal) mode, you will find it is 7FFF (or MAX_SHORT, the maximum 16-bit signed integer value). That's also interesting.
NOTE: You can investigate variable values by using the print command (e.g. print node) and the backtrace using the bt command.
These are coming from the while loop in kruskal (the only place that is calling find), so we need to investigate where that value is coming from. Lets quit out of gdb (press 'q' and enter then confirm with 'y' and enter).
Add the following to the while loop and run the resulting program:
printf("%d: nextedge=%d EDGES[nextedge][0]=%d EDGES[nextedge][1]=%d\n", numedges, nextedge, EDGES[nextedge][0], EDGES[nextedge][1]);
which gives:
0: nextedge=0 EDGES[nextedge][0]=-557487152 EDGES[nextedge][1]=32767
So it looks like EDGES[0] is not being initialized, which points to the if(i<j) condition in the initialization loop above the bubblesort. OK, so lets trace what is happening in the initialization loop by adding the following inside the if loop:
printf("EDGES[%d]: 0=%d 1=%d\n", k, i, j);
Rerunning this, we see that there are no lines associated with this statement, so it is not getting executed.
Changing the if condition to:
if(i<=j)
causes the statement to be executed and the segment fault to go away.

8-Queens snippet

I have currently learning backtracking and got stuck on the 8-queen problem, I am using a 8x8 matrix and I think I've got some problems regarding the matrix passing to functions, any help would be highly apreciated.I wouldn't mind if anyone would bring any optimisation to the code, thanks.
here is my code.
#include <stdio.h>
#include <stdlib.h>
#define MAX 7
//void azzera(int **mat);
void posiziona(int **mat, int r,int c);
void stampa(int **mat);
int in_scacchi(int **mat,int r ,int c);
int main(int argc, char *argv[])
{
int i=0,j=0;
int **mat=(int **)malloc(sizeof(int *)*MAX);
for(i=0;i<=MAX;i++){
mat[i]=(int *)malloc(MAX*sizeof(int));
for(j=0;j<=MAX;j++){
mat[i][j]=-1;
}
}
printf("insert pos of the first queen on the first row (1-8) :");
scanf("%d",&i);
i-=1;
mat[0][i]=1;
posiziona(mat,1,0);
stampa(mat);
system("PAUSE");
return 0;
}
/*void azzera(int **mat){
int i=0,j=0;
for(i=0;i<=MAX;i++){
for(j=0;j<=MAX;j++){
mat[i][j]=-1;
}
}
}*/
void stampa(int **mat){
int i,j;
for(i=0;i<=MAX;i++){
for(j=0;j<=MAX;j++){
printf(" %d",mat[i][j]);
}
printf("\n");
}
}
void posiziona(int **mat, int r,int c){
int i=0,riga=1,flag_col=-1,flag_riga=-1;
if(riga<=7&&flag_riga!=1){
if(flag_riga==1){
flag_riga=-1;
posiziona(mat,r+1,0);
}
else if(in_scacchi(mat,r,c)==1){
if(c==MAX)
posiziona(mat,r-1,0);
posiziona(mat,r,c+1);
}
else{
flag_riga=1;
}
}
}
int in_scacchi(int **mat,int r ,int c){
int i,j,k,m;
int flag=0;
//col
for(i=0;i<r;i++){
for(j=0;j<=c;j++){
if(((mat[i][j]==1)&&(c==j)))
return 1;
}
}
//diag \
for(i=0;i<MAX-r;i++){
for(j=0;j<=MAX-c;j++){
if(mat[MAX-r-i][MAX-c-j]==1)
return 1;
}
}
//antidiag
for(i=r+1;i<=MAX;i++){
for(j=c+1;j<=MAX;j++){
if(mat[r-i][c+j]==1) {
return 1;
}
}
}
return 0;
}
1. One glaring problem is the memory allocation:
int **mat=(int **)malloc(sizeof(int *)*MAX);
for(i=0;i<=MAX;i++){
mat[i]=(int *)malloc(MAX*sizeof(int));
Given that MAX is 7, both mallocs are allocating too little memory for the matrix (seven elements instead of eight).
To be honest, I'd rename MAX to SIZE or something similar, and change all your loops to use strict less-than, i.e.
for(i = 0; i < SIZE; i++) {
I would argue that this is slightly more idiomatic and less prone to errors.
2. I haven't tried to debug the logic (I don't think it's fair to expect us to do that). However, I have noticed that nowhere except in main do you assign to elements of mat. To me this suggests that the code can't possibly be correct.
3. Beyond that, it may be useful to observe that in a valid solution every row of the chessboard contains exactly one queen. This means that you don't really need an 8x8 matrix to represent the solution: an 8-element array of column positions will do.
edit In response to your question in the comments, here is a complete Python implementation demonstrating point 3 above:
def can_place(col_positions, col):
row = len(col_positions)
for r, c in enumerate(col_positions):
if c == col or abs(c - col) == abs(r - row): return False
return True
def queens(n, col_positions = []):
if len(col_positions) >= n:
pretty_print(n, col_positions)
return True
for col in xrange(n):
if can_place(col_positions, col):
if queens(n, col_positions + [col]):
return True
return False
def pretty_print(n, col_positions):
for col in col_positions:
print '.' * col + 'X' + '.' * (n - 1 - col)
queens(8)
Your matrix must iterate from 0 to MAX-1,
i.e
int **mat= malloc(sizeof(int *)*MAX);
for(i=0;i< MAX;i++){ //see for i<MAX
mat[i]= malloc(MAX*sizeof(int));
for(j=0;j<MAX;j++){ //see for j<MAX
mat[i][j]=-1;
}
}
malloc must be called with sizeof(...) * (MAX+1) in both the i- and j-loop.
Moreover, when I ran your program I got an access violation in the antidiag portion of in_scacchi(...) due to the fact that the code tries to access mat[r-i][c+j] which evaluates to mat[-1][1] because r==1 and i==2.
So there seems to be a logical error in your description of the anti-diagonal of the matrix.

Resources