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;
}
}
}
Related
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.)
I have this problem I need to solve. I am given a program which is supposed to allocate memory to create an array of doubles, but something is wrong with it. Basically, main and the function create_array are broken, and I need to fix it. The solution I came up with comes up with a segmentation error and i am not sure why.
First off I decided to delete the "free(array)" in main b/c array is a pointer which does not exist in heap from my understanding.
I tried changing the function "create_array" to the following
void create_array(double *x, unsigned long n) {
double *d = malloc((int)n *sizeof(double));
if(d == NULL){
printf("Sorry Memory Not Available. Program Terminated.\n");
exit(1);
}
x=d;
free(d);
}
Here is what I was provided with:
int main(void) {
printf("\nProgram started...\n");
double *array = NULL;
int n = 20;
create_array(array, n);
if( array != NULL) {
populate_array(array, n);
// displays half of the values of the array
for(int i = 0; i < n/2; i++){
printf("%f\n", *array++);
}
// According to C standard, the program's behaviour, after the following
// call to the function free is considered "Undefined" and needs to be
// fixed.
free(array);
}
printf("Program terminated...\n");
return 0;
}
// THE FOLLOWING FUNCTION IS NOT PROPERLY DESINGED AND NEEDS TO BE FIXED
void create_array(double *x, unsigned long n) {
x = malloc(n *sizeof(double));
if(x == NULL){
printf("Sorry Memory Not Available. Program Terminated.\n");
exit(1);
}
}
void populate_array(double *array, int n) {
int i;
for(i = 0; i < n; i++)
array[i] = (i + 1) * 100;
}
When I run the code with my edit, i get segmentation error. When I run the code with no changes, it simply outputs "program started \n program terminated".
The problem is, in both code and snippet provided, the variable assigned by malloc's return value lives until the function returns. So you need to use pointer-to-pointer. Moreover, in the first snippet, if you free the area allotted already, you can't use the space anymore.
void create_array(double **x, unsigned long n) {
*x = malloc(n *sizeof(double));
if(*x == NULL){
printf("Sorry Memory Not Available. Program Terminated.\n");
exit(1);
}
}
In main, you can call it as create_array(&array, n);.
There are several errors in create_array. x is a local variable, so it will not change. Also, you free the memory after initialization, which in practice makes the whole function useless. Free should be done after you're done with the memory.
Here is a corrected version
void create_array(double **x, unsigned long n) {
double *d = malloc((int)n *sizeof(double));
if(d == NULL){
printf("Sorry Memory Not Available. Program Terminated.\n");
exit(1);
}
*x=d;
}
And then you call it like this:
double *p;
create_array(&p, size);
/* Do something */
free(p);
But, IMHO it would be better to do like this:
double *create_array(size_t n) {
double *d = malloc(n*sizeof(*d));
if(d == NULL){
fprintf(stderr, "Sorry Memory Not Available. Program Terminated.\n");
exit(1);
}
return d;
}
Changes:
Returns the pointer instead of using an output parameter
Use size_t instead of unsigned long
Print errors to stderr insteadd of stdio
Use malloc(size *sizeof(<var>)) instead of malloc(size * sizeof(<type>))
And here is the call:
double *p = create_array(&p, size);
/* Do something */
free(p);
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;
}
#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.
Im trying to make a simple encryption program, nothing mathematical or so but to go further I need to know what causes the segmentation fault in my program. I have tried to simplify my code..
char *
createAlfabeth(void)
{
char * alfa = NULL;
strcpy(alfa, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
int i, j=1, k=0;
for(i=0; i<(sizeof(alfa)/sizeof(char)); i++, j+=3)
{
if(j>25)
{
j=1+(k++);
}
swap(alfa, i, j);
}
return alfa;
}
char *
codificator(char *mess, const char *alfa)
{
int key[]=PRIVATE_KEY;
char *newmess=NULL;
int i, j;
for(i=0, j=0; mess[i]!='\0'; i++, j++)
{
if(j>(sizeof(key)/sizeof(key[0])))
{
j=0;
}
newmess[i]=alfa[i+key[j]];
}
return newmess;
}
int
main(void)
{
char *alfa=crearAlfabeto();
printf("write your message :\n");
char message[20];
scanf("%s", message);
char *codified=codificator(message, alfa);
printf("The codified message is: %s \n", codified);
return 0;
}
SOLVED: POST MEMORANDUM
I solved the problem with the recommendations by ouah and askmish below (thanks to both). And for you people googling to this answer, I want to say that this problem has to do with the heap handling. As I did not store enough space for the strings that I declared later or initialized there was not enough memory allocated to them.
This is was the malloc, realloc, calloc (and free) functions purpose is to handle. The segmentation fault comes from that I tried to move beyond the allocated memory for the data segment in the code. Every program allocated memory for the code (code segment), and data (data segment) and by not telling explicitly in c how much you are going to store in data segment you get this error. This is my understanding of what I have read, if someone with more insight wants to comment on this please do..
char * alfa = NULL;
strcpy(alfa, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
You need to allocate memory for your array object.
For example:
char *alfa = malloc(sizeof "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
/* check that malloc succeeds here */
strcpy(alfa, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
In addition to ouah's answer:
Instead of this in codificator:
char *newmess=NULL;
int i, j;
for(i=0, j=0; mess[i]!='\0'; i++, j++)
{
if(j>(sizeof(key)/sizeof(key[0])))
{
j=0;
}
newmess[i]=alfa[i+key[j]];
}
Write this:
char *newmess=NULL;
int i, j;
newmess = malloc(strlen(mess)*sizeof(char)); //This line could be written in many ways
if(newmess != NULL) //Handle memory allocation failing.
{
for(i=0, j=0; mess[i]!='\0'; i++, j++)
{
if(j>(sizeof(key)/sizeof(key[0])))
{
j=0;
}
newmess[i]=alfa[i+key[j]];
}
}
Please ensure you allocate memory to the pointers before using them with strings.Else you will get Seg Faults.
You have to use the fix of both mine and ouah's to remove the segmentation faults.