Why am i getting EXC_BAD_ACCESS (code=1, address=0x0)? - c

I am trying to write a program that, when given a certain price, will break it into 20s, 10s, 5s and 1s.
However, I am getting the following error: EXC_BAD_ACCESS (code=1, address=0x0)
The error shows up on the line: *tens=diff in the function.
I do not understand what is wrong!
Here is the code:
#include<stdio.h>
#include<stdlib.h>
void pay_month(int , int *, int *, int *, int *);
int main(){
int dollars, *twenties=0, *tens=0, *fives=0, *ones=0;
printf("enter amount to pay: ");
scanf("%d",&dollars);
pay_month(dollars, twenties, tens, fives, ones);
return 0;
}
void pay_month(int dollars, int *twenties, int *tens, int *fives, int
*ones){
int diff=0;
int odolls;
odolls=dollars;
while(dollars%20!=0){
dollars=dollars-1;
diff++;
}
*tens=diff;
*twenties=dollars/20;
diff=0;
while(*tens%10!=0){
*tens=*tens-1;
diff++;
}
*tens=*tens/10;
*fives=diff;
diff=0;
while(*fives%5!=0){
*fives=*fives-1;
diff++;
}
*ones=diff;
diff=0;
while(*ones%1!=0){
*ones=*ones-1;
diff++;
}
printf("in %d there is %d twentis %d tens %d fives and %d ones\n",odolls, *twenties, *tens, *fives, *ones);
}

You are dereferencing a NULL pointer. That is, you are asking the computer to write into memory location 0. You are not allowed to do that.
I think what you've done is used pointers without quite understanding how to obtain them. Possibly just to stop the compiler from throwing errors.
This simple change should solve the problem:
int dollars, twenties=0, tens=0, fives=0, ones=0;
printf("enter amount to pay: ");
scanf("%d",&dollars);
pay_month(dollars, &twenties, &tens, &fives, &ones);
Notice that none of the values in the calling function are pointers anymore. They're just integers. You prefix with & when passing them to pay_month. That's the reference operator, which obtains a pointer to where the value is stored.
Now, when you dereference the tens pointer inside pay_month, you're actually accessing the same part of memory where the value tens is stored on the stack in main.

a classic case of pointers and variables
essentially when you are declaring pointer as
int *twenties=0, *tens=0, *fives=0, *ones=0;
you are essentially making these pointers to point to NULL memory which means no memory is allocated to those.
one way to solve this is by declaring these as variables and passing the address of these variables
int dollars, twenties=0, tens=0, fives=0, ones=0;
and
pay_month(dollars, &twenties, &tens, &fives, &ones);

Related

Segmentation Fault when using FOR loop but not when using WHILE in an implementation of qsort on an array of pointers

I currently am beginning at C programming, my long term objective being teaching myself reverse engineering, and I am following the excellent book by Denis M. Ritchie. I chose this book despite it being written in the 90s because of the great care the authors paid to explanations and examples throughout it.
Anyway, I was playing with the quicksort algorithm the authors described in section 5.6, and tried to rewrite it by recall, but had trouble because of a segmentation fault that I tried to debug with gdb. The code was :
#include <stdio.h>
#define MAX 10000
void sort(int **, int, int);
int main(){
int tab[MAX]={18,7,43,72,2365,743,234,3215,13,456}, i;
int *ptrtab[MAX];
for (i=0; i<MAX && tab[i]>0; i++){
ptrtab[i]=&tab[i];
}
sort(ptrtab, 0, i-1);
for (;i>0;i--) printf ("%d\n",*ptrtab[i]);
return 0;
}
void sort(int **ptrtab,int gauche,int droite){
int i, dernier;
void echanger(int **, int, int);
if (gauche>=droite) return;
dernier=gauche;
for (i=gauche+1; i<=droite; i++){
if (*ptrtab[i]< *ptrtab[gauche])
echanger(ptrtab, ++dernier, i);
}
echanger(ptrtab, gauche, dernier);
sort(ptrtab,dernier+1,droite);
sort(ptrtab,gauche, dernier);
}
void echanger(int **ptrtab,int a,int b){
int *temp=ptrtab[a];
ptrtab[a]=ptrtab[b];
ptrtab[b]=temp;
}
Long story short, after identifying the line in cause (for (;i>0;i--) printf ("%d\n",*ptrtab[i]);)I put a break on it, and the segmentation fault crashed the program on the first iteration of the for loop, and printf wasn't executed. So I just changed this line in my code to put a while loop instead :
#include <stdio.h>
#define MAX 10000
void sort(int **, int, int);
int main(){
int tab[MAX]={18,7,43,72,2365,743,234,3215,13,456}, i;
int *ptrtab[MAX];
for (i=0; i<MAX && tab[i]>0; i++){
ptrtab[i]=&tab[i];
}
sort(ptrtab, 0, i-1);
while (i>0) printf ("%d\n",*ptrtab[--i]);
return 0;
}
void sort(int **ptrtab,int gauche,int droite){
int i, dernier;
void echanger(int **, int, int);
if (gauche>=droite) return;
dernier=gauche;
for (i=gauche+1; i<=droite; i++){
if (*ptrtab[i]< *ptrtab[gauche])
echanger(ptrtab, ++dernier, i);
}
echanger(ptrtab, gauche, dernier);
sort(ptrtab,dernier+1,droite);
sort(ptrtab,gauche, dernier);
}
void echanger(int **ptrtab,int a,int b){
int *temp=ptrtab[a];
ptrtab[a]=ptrtab[b];
ptrtab[b]=temp;
}
And this code works now.
I know there must be quite a few errors throughout my code as I am just a beginner, but I can't grasp the reason why changing from a for to a while loop made a difference...
Note that I am using GCC on ubuntu 16.04.
Thank you all for your attention, and sorry for the rambling.
Kind regards,
S. A.
Your while loop is actually different to the for loop. The while loop decrements i before using it; the for loop does not.
In:
for (;i>0;i--) printf ("%d\n",*ptrtab[i]);
The loop starts with the last value of i from the previous loop, where either it reaches the end of the array (so i will be MAX), or indexes tab at a point where it is zero.
In the first case, ptrtab[MAX] will be indexed, which is invalid, in the second case an uninitialized entry of ptrtab will be used, which, being an automatic variable, will have a random value (points to a random memory location, which will likely be invalid (undefined behaviour).

Pointers in C for a rookie

I am just starting to learn programming for a unit I am doing in my engineering course and I have come across pointers. I just wanted some reassurance that I actually understand the concept correctly in terms of using a pointer as an argument in a function. If I understand it correctly, you pass a pointer to an address of a variable you would like to be altered by a separate function called, even though it is a local variable within the scope of the calling function. Does that make sense? I have an example from my text book which I re-wrote. The only thing is they gave it in two incomplete parts and I put it together, filled in the blanks and added the final printf statement in the main function. I'll paste it here:
#include <stdio.h>
#include <stdlib.h>
#define READ_OK 0
#define READ_ERROR 1
int read_num(int lo, int hi, int *num);
int main(int argc, char *argv[])
{
int lo = 0, hi = 0, *num, val;
printf("Please enter a lower bound and an upper bound for your range,respectively\nLower: ");
scanf("%d", &lo);
printf("Upper: ");
scanf("%d", &hi);
num = &val;
if(read_num(lo,hi, &val) != READ_OK)
{
printf("Read error, program abort\n");
exit(EXIT_FAILURE);
}
else
{
printf("You entered %d, press any key to continue: \n", val);
getchar();
}
return 0;
}
int read_num(int lo, int hi, int *num)
{
int next;
printf("Enter a number between %d and %d: ", lo, hi);
while(scanf("%d", &next)==1)
{
if (lo<=next && next<=hi)
{
*num = next;
return READ_OK;
}
printf("%d is not between %d and %d\nTry again: ", next, lo, hi);
}
return READ_ERROR;
}
So is my understanding correct? "val" gets modified in read_num() by passing it's address in the form of pointer "*num", in which the the value for "next" is then written?
PS: is this syntax correct?
PPS: What would this process specifically be called?
Thanks a bunch for any help :)
The *num is not necessary inside the main() function. As you are passing the address of the val inside the read_num() , so any changes from the read_num() will also affect the value inside main() as you are working with the address.
In your program you have basically use two different pointers- one is inside main which is num, and another inside read_num() which is also num, for more understanding see the scope of a variable in c. As the val is inside main so you don't need to use pointer here, because you have the access of changing the value from the main as it is local to it. You will need pointer when you will be changing the value of val outside from the main, or from outside of the scope of the variable.

Why this program stops unexpectedly in the middle of the input

i have written this code for a question on codechef (A4)....when i give the input:
2
4 2
This program stops unexpectedly without taking further input ....can some please point out the mistake in the code?
#include <stdio.h>
#include<math.h>
void number(long int a,int b)
{
int c;
c=b;
int first[c],last[c],e=1,i;
long int d;
d=pow(a,a);
for(i=(c-1);i>=0;i--)
{
last[i]=fmod(d,pow(10,e));
e++;
}
e=1;
while(d>pow(10,(b-1)))
d/=10;
for(i=(c-1);i>=0;i--)
{
first[i]=fmod(d,pow(10,e));
e++;
}
for(i=0;i<c;i++)
printf("%d",first[i]);
printf(" ");
for(i=0;i<c;i++)
printf("%d",last[i]);
printf("\n");
}
int main()
{ int T;
scanf("%d",&T);
while(T--)
{ long int a;
int b;
scanf("%ld %d",a,b);
number(a,b);
}
return 0;
}
scanf("%ld %d",&a,&b);
Using uninitialized variables lead to UB. You should use &a and &b to scan variables
In your code you have
scanf("&ld %d",a,b);
It means you're trying to input integers to the memory locations of values of a and b. For and example let value of a = 1234566466 (long int), and b = 1234 (int). Accordingly 1234 is a memory location which is at the start of the RAM. Tn that area System files are loaded. So you are going to change system behaviour. That is not allowed.
Further when the complier allocate some memory space to your program, you can access only the memory which is inside your memory segment directly. But above statement trying to access another segment.
That's why you get segmentatin fault.
You are passing an integer to a function that expects a pointer, for scanf the "%d" and "%ld" specifiers expect int * and long int * respectively, and you pass int and long int, so when trying to access the integers as if they were memory addresses the segmentation fault occurs.
The correct way to call scanf would be as Gopi said
scanf("%ld %d", &a, &b);
there you pass a and b addresses instead of their values.

Declaring arrays in c language without initial size

Write a program to manipulate the temperature details as given below.
- Input the number of days to be calculated. – Main function
- Input temperature in Celsius – input function
- Convert the temperature from Celsius to Fahrenheit.- Separate function
- find the average temperature in Fahrenheit.
how can I make this program without initial size of array ??
#include<stdio.h>
#include<conio.h>
void input(int);
int temp[10];
int d;
void main()
{
int x=0;
float avg=0,t=0;
printf("\nHow many days : ");
scanf("%d",&d);
input(d);
conv();
for(x=0;x<d;x++)
{
t=t+temp[x];
}
avg=t/d;
printf("Avarage is %f",avg);
getch();
}
void input(int d)
{
int x=0;
for(x=0;x<d;x++)
{
printf("Input temperature in Celsius for #%d day",x+1);
scanf("%d",&temp[x]);
}
}
void conv()
{
int x=0;
for(x=0;x<d;x++)
{
temp[x]=1.8*temp[x]+32;
}
}
In C arrays and pointers are closely related. In fact, by design an array is just a syntax convention for accessing a pointer to an allocated memory. *(see note for more details below)
So in C the statement
anyarray[n]
is the same as
*(anyarray+n)
Using pointer arithmetic.
You don't really have to worry about the details to make it "work" as it is designed to be somewhat intuitive.
Just create a pointer, and allocate the memory and then access it like as an array.
Here is some examples --
int *temp = null; // this will be our array
// allocate space for 10 items
temp = malloc(sizeof(int)*10);
// reference the first element of temp
temp[0] = 70;
// free the memory when done
free(temp);
Remember -- if you access outside of the allocated area you will have unknown effects.
To be clear it is the indexing operator ([ ]) that is translated to pointer arithmetic. This is not an array in the modern sense of the
type. Whether (or not) the pointer involved points to (dynamically) allocated
memory is inconsequential to how this operator works. In a more modern language you would be able to operate on the array as an abstract type (to see how big it is, for example), you can't do this in C.
An array without an initial size is basically just a pointer. In order to dynamically set the size of the array, you need to use the malloc() or calloc() functions. These will allocate a specified amount of bytes of memory.
In your code above, declare temp as an int pointer
int *temp;
Then allocate space for it using malloc() or calloc(). The argument that these functions take is is the number of bytes of memory to allocate. In this case, you want enough space for d ints. So...
temp = malloc(d * sizeof(int));
malloc returns a pointer to the first byte in the block of memory that was just allocated. Regular arrays are simply pointers to the first byte in a sectioned off block of memory, which is exactly what temp is now. Thus, you can treat the temp pointer as an array! Like so:
temp[1] = 10;
int foo = temp[1];
printf("%d", foo);
Outputs
10
You will need to declare temp as an int pointer (instead of an int array). Then, you can use malloc in your main (after your first scanf):
temp = malloc(d * sizeof(int));
If your compiler supports c99, then simply use VLA(variable length array).Use like this:
void input(int);
int d;
void main()
{
int x=0;
float avg=0,t=0;
printf("\nHow many days : ");
scanf("%d",&d);
int temp[d];
input(d);
conv();
for(x=0;x<d;x++)
{
t=t+temp[x];
}
avg=t/d;
printf("Avarage is %f",avg);
getch();
}
Now temp[] is defined inside main() after date input.
1-add #include<stdlib.h> at the top of your file. Then modify the conv() code as follows:
2- modify temp declaration as follows (global variable):
int *temp;
3- modify input(int d) function as follows (tested on Visual Studio 2010):
void input(int d)
{
int x=0;
temp=(int*)malloc(sizeof(int)*d);
for(x=0;x<d;x++)
{
printf("Input temperature in Celsius for #%d day",x+1);
scanf("%d",&temp[x]);
}
}
Allocate the "array" dynamically on the heap after you read the size.
I didn't change anything else so you may see it clearly.
#include<stdio.h>
#include<conio.h>
#include <stdlib.h> //here
void input(int);
int *temp=0; //here
int d;
void main()
{
int x=0;
float avg=0,t=0;
printf("\nHow many days : ");
scanf("%d",&d);
temp=malloc(d * sizeof(int)); //here
input(d);
conv();
for(x=0;x<d;x++)
{
t=t+temp[x];
}
avg=t/d;
printf("Avarage is %f",avg);
getch();
}
void input(int d)
{
int x=0;
for(x=0;x<d;x++)
{
printf("Input temperature in Celsius for #%d day",x+1);
scanf("%d",&temp[x]);
}
}
void conv()
{
int x=0;
for(x=0;x<d;x++)
{
temp[x]=1.8*temp[x]+32;
}
}
Maybe it's late to answer but...
If you work with small embedded system you might not have malloc and free functions.
So you have to sacrifice memory for 366 * sizeof(your_type), define it statically and use as a circular buffer. Then you can always slice it by number of days you need to calculate an average value.
Of course this makes natural constrains. You can define it by yourself.

My C Program has stopped working

I am trying to do my homework here, which is writing a program, that shows the distances to (0,0) of a certain number of points. However for some reason(s) as soon as my program starts, windows says that it has stopped working. I tried it with two different compilers, and they don't give me any error messages.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct point {
int x;
int y;
};
struct point getPoint();
void printPoint(struct point);
double distanceToO(struct point p);
void createArray(struct point, int);
int main() {
int number, i;
struct point coord[number];
printf("Type the number of points you want to create: ");
scanf("%d", &number);
printf("\n\n");
for(i=0;i<number;i++)
coord[i]=getPoint();
printf("\n\t\tPoint\tDistance to (0,0)\n");
for(i=0;i<number;i++) {
printPoint(coord[i]);
printf("\t%0.2lf", distanceToO(coord[i]));
}
system("pause");
return 0;
}
struct point getPoint() {
struct point p;
printf("Type the x and the y-value for a point with a space in between: ");
scanf("%d %d", &p.x, &p.y);
return p;
}
void printPoint(struct point p){
printf("\n\t\t(%d,%d)",p.x,p.y);
}
double distanceToO(struct point p) {
return sqrt((0-p.x)*(0-p.x)+(0-p.y)*(0-p.y));
}
That is what's to do in detail:
Write a Program, that first asks how many points should be created, and then asks the user for the x and y values of the points.
Then the Program should give out a table, showing the Point and the distance to (0,0).
The following functions have to be created/used:
"point getpoint()" - which asks to enter the coordinates
"void printpoint(point p)" - which prints the coordinates of the points
"double distanceToO(point p)" - returns the distance to (0,0)
Create a structure point, that has two members the x-coordinate and the y-coordinate of a point.
Can somebody give me a hint on what's wrong?
int number, i;
struct point coord[number];
number has not been initialized, and you are using it to declare the size of the coord array. You will be generating an array of effectively random size on the stack, which may well cause a crash.
The variable number is uninitialized when used to specify the number of elements in the array coord. The array is then accessed and it is not known how many elements are in they array. Read a valid value into number before using it and check that a valid value has definitely been read:
/* scanf() returns number of assignments made. */
if (scanf("%d", &number) == 1)
{
}
Always check the result of input operations to ensure subsequent code is processing variables with valid values.
int number;
struct point coord[number];
I don't see where number is initialized. If you really want to use VLA, you should declare coord afterwards:
int number;
scanf("%d", &number);
struct point coord[number];
Otherwise, since number has an automatic storage duration, its value will be undefined.
I'm pretty surprised you don't get a warning/error on this:
int number, i;
struct point coord[number];
You allocate an array of struct point with a size equal to an unitialized variable.
Note that if you use Visual Studio, it doesn't fully support C99 standard either so it's not allowed to have statements before declarations, as in:
int number;
number = some_number;
struct point coord; // Error, you have a statement above

Resources