fail to pass argument to self-written function - c

i write a merge sort program. But it came to segmentation fault (core dumped) when it run.
here is the code:
#include<stdio.h>
#include<stdlib.h>
int* input_array(size_t *);
void divide_and_conquer_sort(int *restrict, size_t, size_t);
int main(void){
size_t LEN=0;
int *array;
array=input_array(&LEN);
puts("Here is a sort to all array's elements from small to large:");
divide_and_conquer_sort(array, 0, LEN-1);
for(size_t i=0; i<LEN; i++)printf("%d\040", array[i]);
putchar('\n');
return 0;}
int* input_array(size_t *ptr_to_LEN){
int *array=(int*)malloc(sizeof(int));
static char buf[BUFSIZ];
void *alloc_check;
fprintf(stdout, "Enter decimal integer arrays(use spaces key to separate every number):\n");
while(fscanf(stdin, "%d", array+*ptr_to_LEN)==1)
{
alloc_check=realloc(array, (*ptr_to_LEN+2)*sizeof(int));
if(alloc_check!=NULL)array=(int*)alloc_check;
(*ptr_to_LEN)++; if(getchar()=='\n')break;
}
if(*ptr_to_LEN==0)
{
fprintf(stderr, "no number entered correctly.\n");
exit(EXIT_FAILURE);
}
return array;}
void divide_and_conquer_sort(int *restrict array, size_t left, size_t right){
size_t middle;
middle=(left+right)/2;
divide_and_conquer_sort(array, left, middle);
divide_and_conquer_sort(array, middle+1, right);
if(left==right)return;
int *sub_array=(int*)malloc((right-left+1)*sizeof(int));
size_t i, j, k;
i=left; j=middle+1; k=0;
while(i<=middle && j<=right)
{
if(*(array+i)<*(array+j))
{
*(sub_array+k)=*(array+i);
i++;
}
else
{
*(sub_array+k)=*(array+j);
j++;
}
k++;
}
while(i<=middle)
{
*(sub_array+k)=*(array+i);
i++;
k++;
}
while(j<=right)
{
*(sub_array+k)=*(array+j);
j++;
k++;
}
for(k=0; k<=right-left; k++)
*(array+k+left)=*(sub_array+k);
return;
}
the input_array is an array input function. It gets the address of LEN and modified LEN value by its address. Actually LEN is the length of input array. but when i want to pass LEN-1 to divide_and_conquer_sort, it failed!
i used gdb debugger that told me
0x00right=<error reading variable: Cannot access memory at address 0x7fffff7eefc8>)
why LEN-1 can't be serve as argument in divide_and_conquer_sort?

You're recursing indefinitely and have exhausted the available stack space. That's why the debugger can't read the address of right, which is on the stack.
Just from looking at the code you can see what the problem is: every call to divide_and_conquer_sort always results in two more calls to divide_and_conquer_sort. There needs to be some kind of end condition where you return without calling divide_and_conquer_sort, for example when left and right are the same. (It's there! Just in the wrong place.)

Related

keeps saying Segmentation fault

This code keeps saying segmentation fault.
for(i=0; i<(numTopps-1); i++)
{
if(kcalTopp[i]<kcalTopp[i+1])
{
temp=*kcalTopp[i];
*kcalTopp[i]=*kcalTopp[i+1];
*kcalTopp[i+1]=temp;
}
}
I think above part is a problem.
but I can't figure what is the problem
#include <stdio.h>
#include <stdlib.h>
void sort(int *kcalTopp[], int numTopps);
int main(void)
{
int numTopps, doughPrice, eachToppPrice, kcalDough, i, j, totalKcal, highest, kcalperDol;
scanf("%d %d %d %d", &numTopps, &doughPrice, &eachToppPrice, &kcalDough);
int *kcalTopp;
kcalTopp=(int*)malloc(sizeof(int)*numTopps);
for(i=0; i<numTopps; i++)
{
scanf("%d", &kcalTopp[i]);
}
totalKcal=kcalDough;
highest=totalKcal/doughPrice;
sort(&kcalTopp, numTopps);
for(i=0; i<numTopps; i++)
{
for(j=0; j<=i; j++)
{
totalKcal=totalKcal+kcalTopp[j];
kcalperDol=totalKcal/(doughPrice+i*eachToppPrice);
if(kcalperDol>highest)
{
highest=kcalperDol;
}
}
}
printf("%d", highest);
return 0;
}
void sort(int *kcalTopp[], int numTopps)
{
int temp, i;
for(i=0; i<(numTopps-1); i++)
{
if(kcalTopp[i]<kcalTopp[i+1])
{
temp=*kcalTopp[i];
*kcalTopp[i]=*kcalTopp[i+1];
*kcalTopp[i+1]=temp;
}
}
}
Indeed, your problem is the sort function you described, as you suspected. Are you aware what *kcalTopp[i]=*kcalTopp[i+1]; does exactly? You get as parameter an int *array[] which is equivalent to int **array (you can see it as an array of arrays of ints). So when you tell C to access array[i] you will access the i-th array. This is a pointer, and in fact *kcalTopp[i] will be the first element from the i-th array. What you are doing here is swapping first elements from the arrays, but in practice you have a single array of ints (or more technically, an array of length 1 of arrays). The simplest fix is to write:
temp=(*kcalTopp)[i];
(*kcalTopp)[i]=(*kcalTopp)[i+1];
(*kcalTopp)[i+1]=temp;
just to change the precedence of the operators. Now, what we achieved is: we take the first array from the array list (it's the only one we have, isn't it?) with (*kcalTopp); this is an int *, not int ** anymore. Now you can safely access the i-th element from it.
Without parentheses, you would first access the i-th array, because in *kcalTopp[i], the [i] part will execute before the * part.
Anyway, to simplify things, you are not required to take as parameter an int *kcalTopp[], you can simply take int kcalTop[] or int *kcalTopp and not use * anymore:
temp = kcalTopp[i];
kcalTopp[i] = kcalTopp[i+1];
kcalTopp[i+1] = temp;
The original code in your post is using an extra (unnecessary) layer of indirection for kcalTopp, resulting in attempts to manipulate an array of addresses (pointers) as opposed to manipulating int values pointed to in memory. This in turn is likely to be the reason you are seeing segmentation faults, which occur when attempting to access memory that you do not own. For some input values, and depending on what day you run your program, it may run, and it may crash.
(This is sometimes referred to as undefined behavior, and is the reason that the problem will not always manifest itself, making you think your program is flawless, when it is not.)
The following contains edits to your original code for the purpose of illustrating some of the suggestions in comments. (not to fix every logic error.) The edits do include treating kcalTopp as a pointer to int memory as opposed to an array of int *. See in-line comments for clarifications:
//void sort(int *kcalTopp[], int numTopps);//*kcalTopp[] is an array of pointers
void sort(int *kcalTopp, int numTopps);//*kcalTopp is a pointer to 'int' memory
int main(int argc, char *argv[])
{
int numTopps, doughPrice, eachToppPrice, kcalDough, i, j, totalKcal, highest, kcalperDol;
//scanf("%d %d %d %d", &numTopps, &doughPrice, &eachToppPrice, &kcalDough);
if(argv != 5) //simple reading in of command line args
{
printf("4 input values required. Exiting");
return 0;
}
//note, each of these calls includes simple for test for success before going on
numTopps = strtol(argv[1], (char **) NULL, 10);
if(errno == ERANGE) {printf("argv[1] Bad input, exiting"); return 0;}
doughPrice = strtol(argv[2], (char **) NULL, 10);
if(errno == ERANGE) {printf("argv[2] Bad input, exiting"); return 0;}
eachToppPrice = strtol(argv[3], (char **) NULL, 10);
if(errno == ERANGE) {printf("argv[3] Bad input, exiting"); return 0;}
kcalDough = strtol(argv[4], (char **) NULL, 10);
if(errno == ERANGE) {printf("argv[4] Bad input, exiting"); return 0;}
int *kcalTopp;
//This statement (without cast) is sufficient to create memory for kcalTopp
kcalTopp = malloc(sizeof(int)*numTopps);
if(!kcalTopp)//should always test before using memory
{
printf("memory allocation failed, exiting");
return 0;
}
for(i=0; i<numTopps; i++)
{
scanf("%d", &kcalTopp[i]);
}
totalKcal=kcalDough;
highest=totalKcal/doughPrice;
//sort(&kcalTopp, numTopps);
// ^ not needed
sort(kcalTopp, numTopps);
for(i=0; i<numTopps; i++)
{
for(j=0; j<=i; j++)
{
totalKcal=totalKcal+kcalTopp[j];
kcalperDol=totalKcal/(doughPrice+i*eachToppPrice);
if(kcalperDol>highest)
{
highest=kcalperDol;
}
}
}
printf("%d", highest);
return 0;
}
void sort(int *kcalTopp, int numTopps)//note removal of []
{
int temp, i;
for(i=0; i<(numTopps-1); i++)
{
if(kcalTopp[i]<kcalTopp[i+1])
{
temp=kcalTopp[i];//note removal of '*' from all kcalTopp
kcalTopp[i]=kcalTopp[i+1];
kcalTopp[i+1]=temp;
}
}
}

excess # in printing array elements in c

I've written a c program to recursively reverse a 10 char array:
#include<stdio.h>
void rev(char *, char *);
int a = 0;
void main()
{
char in[10], out[10];
scanf("%s", in);
rev(in, out);
printf("in is:%s\n", in);
printf("out is:%s\n", out);
for(a = 0; a < 10; a++)
{
printf("out[%d] is:%c\n", a, out[a]);
}
}
void rev(char *in, char *out)
{
if(a < 10)
{
a++;
rev(in, out);
out[9 - (--a)] = in[a];
}
}
but it returns an # at the end of array when I print the whole array while when I print array elements one by one, it doesn't exists.
please tell me what it is?
rev is reversing the entire in array, not just the part that contains the user's input. So it's copying the uninitialized values after the input.
The reason you're seeing different output when you print out than when you print the individual characters is because you're not adding a null byte to out. So printing the string goes past the end of the array when it looks for the null byte.
You should only reverse the part of the array up to strlen(in) rather than the entire array.
You also should pass a as a parameter, not use a global variable.
And finally, when you reach the end you need to add a null byte to the output string.
void rev(char *in, char *out, start, len)
{
if(start < len)
{
rev(in, out, start + 1, len);
out[len - start-1] = in[start];
} else {
out[start] = '\0';
}
}
And call it:
rev(in, out, 0, strlen(in));

Difference between char array[100] and char *array when calling functions?

i'd like to know why this code works fine with char tab[100] but doesn't work if I use char *tab ? fgets function takes a char* array as a parameter right ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Int Palindrome(char* str, int i, int j);
int main()
{
char tab[100];
printf("Enter your string : \n");
fgets(tab, 100, stdin);
int j = strlen(tab);
printf("%d\n", Palindrome(tab, 0, j - 2));
return 0;
}
int Palindrome(char* str, int i, int j)
{
if (i >= j)
{
printf("My word is a Palindrome !\n");
return printf("<(^w^)>\n");
}
else if (str[i] != str[j])
{
printf("My word is not a Palindrome !\n");
return printf("<(X.X)>\n");
}
else
{
return Palindrome(str, i + 1, j - 1);
}
}
With "not work" you probably mean you get some serious error reported like a segmentation fault.
The difference between char tab[100] and char *tab is that the first has storage allocated and the second hasn't. When you call a function with an array as a parameter, then the compiler passes a pointer to the first element of the array, so for the function that got called it doesn't see the difference whether it is called with an array-parameter or with a pointer-parameter.
So to let your program work with char *tab; you must first allocate storage to this pointer, such as with char *tab=malloc(100); Now that there is valid storage allocated (and the pointer now points to it), you can call your function with this tab as parameter.

Segmentation fault (11) when using malloc inside a function to form a string

I'm trying to use a function to assign space and fill that space (or at least some of it) with characters to form a string. Within the function I make a call to malloc, and within the same function I assign characters to the given space. The following code gives the general gist of what I'm doing:
#define INITIAL 10
int func(char **s);
int
main(int argc, char **argv) {
char *s;
int n;
n = func(&s);
printf("Done\n");
return 0;
}
int
func(char **s) {
int i;
*s = (char*)malloc(INITIAL*sizeof(char));
assert(*s);
for (i=0; i<5; i++) {
printf("i=%d\n", i);
*s[i] = 'a'; /*'a' is an arbitrary char for this example */
}
return i;
}
The output of this code is:
i=0
i=1
i=2
Segmentation fault: 11
The reason I have my function return an int is because I ultimately want the function to return the length of the string I have formed.
I'm completely unsure why I am getting a segmentation fault; it seems I have assigned enough space to fit the next char in. It also seems weird to me that it stops at i=2.
If anyone could identify the mistakes I have made I would greatly appreciate it!
Instead of
*s[i] = 'a';
you want
(*s)[i] = 'a';
*s[i] is equivalent to *(s[i]). That is, it treats s as an array of strings and gives you the first character of the string at index i.
*s[i] first calculate s[i], which won't be valid place for i!=0, then dereference it and try to put 'a' there. It may cause Segmentation Fault.
Try changing *s[i] to (*s)[i].
Postfix [] has higher precedence than unary *, so *s[i] is being parsed as *(s[i]), which isn't what you want; you want to dereference s and index into the result, so you need to explicitly group the * operator with s: (*s)[i].
You may want to use size_t instead of an int. Or ssize_t if you need the function to return a negative value:
#include <stdio.h>
#include <stdlib.h>
#define INITIAL 10
ssize_t func(char **);
int main(void)
{
char *s;
if((func(&s)) == -1)
{
printf("An error occurred\n");
return 1;
}
printf("Done\n");
free(s);
return 0;
}
ssize_t func(char **s)
{
size_t i = 0;
if ( INITIAL < 1 )
return -1;
if (!(*s = malloc(INITIAL*sizeof(char))))
return -1;
for (i=0; i< 5; i++) {
printf("i=%zu\n", i);
(*s)[i] = 'a';; /*'a' is an arbitrary char for this example */
}
return i;
}

Segmentation Fault in C using calloc

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int queensonboard(int n,int m)
{
int count=0,i,j,flag,x[100];
char **board;
/* board= (char**)calloc(sizeof(char*),n);
for(i=0;i<n;i++)
{
board[i]= (char*)calloc(sizeof(char),m);
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%c",&board[i][j]);
}
}*/
// x==(int*)calloc(sizeof(int),n);
flag=0;
for(i=0;i<n;i++)
{
x[i]=0;
}
while(i>0)
{
while(x[i]<m)
{
x[i]++;
// if(board[i][x[i]]!='#')
// {
for(j=0;j<i;j++)
{
if(x[j]==x[i])
{
flag=1;
}
else if(x[j]-x[i]==abs(j-i))
{
flag=1;
}
else
{
flag=0;
}
}
if(flag==0 && i==n-1)
{
count++;
}
else if(flag==0)
{
i++;
}
//}
}
x[i]=-1;
i--;
}
printf("%d\n",count);
}
int main() {
int i,n,m,j;
scanf("%d",&i);
for(j=1;j<=i;j++)
{
scanf("%d %d",&n,&m);
queensonboard(n,m);
}
return 0;
}
This is the code. The program gives segmentation fault on dynamically allocating any of the arrays x or board.(Commented here.)
That is when i try to allocate with calloc.
Couldnt really figure out why this is happening. Tried changing thins and that but still happening.
The definition of calloc is as follows:
void *calloc(size_t num, size_t size);
num Number of elements to allocate.
size Size of each element.
You have your arguments swapped. It should be like this:
board = calloc(n, sizeof(char *));
for(i = 0; i < n; i++)
{
board[i]= calloc(m, sizeof(char));
}
Also, this line is incorrect:
x == (int*)calloc(sizeof(int), n);
This, is comparing the address of x to the address that calloc returns. The logic is incorrect too. The way you have x defined, it is an array of 100 ints.
If you want an array of int pointers, you need to do this:
int *x[100];
If you want a pointer to array of 100 ints, you need to do this:
int (*x)[100];
If you're simply trying to allocate memory for x, you've already accomplished that with your declaration:
int x[100];
The obvious explanation for a segmentation fault is that you are de-referencing an invalid pointer. The obvious way for that to happen would be for any of the calls to calloc to return NULL. And calloc does that when it fails. You are not checking the return value of calloc for errors and I think it very likely that one of the calls returns NULL because you supplied invalid parameters.
So, debug the problem by checking the return value of the calls to calloc, and checking the input parameters that you pass. I know it's frustrating to have to do this, but you must check for errors in all user input, and you must check the return values of all calls to memory allocation functions.
This line
x==(int*)calloc(sizeof(int),n)
where you perform comparison rather than assignment is also clearly problematic. You meant:
int *x = calloc(n, sizeof(int));
And yes, you have the arguments to calloc swapped as others point out. You should certainly fix that but I do not believe that to be the cause of your problem.

Resources