How to resolve this segmentation fault inside my do-while loop? - c

You have to transport a maximum of 15 different loads from one port to another. Carrying capacity of a cargo ship, which will transport those loads, is 50 tons. Loads are enumerated and the information about the weight of every load is given as input.
Suppose that the weight of every load is smaller than or equal to 50 tons and greater than 0.
You will read the weight of every load from the input in a single line. Your input will end with a -1. You will print the number of trips necessary.
Sample Input:
50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 -1
Output:
15
But I get this error and whenever I give input to program
./vpl_execution: line 5: 15093 Bus error (core dumped) ./main
By the way I seached about this situation, I think I am not out of array index or wrong using wrong pointers. Also, I saw same question in here with some solution but I want to know why code is not working and then solve the question on my own. Thank you so much for your help, all.
#include <stdio.h>
int main()
{ int w,i,t,sum,index;
int list[16];
w = 1;
do
{
scanf("%d",&w);
list[index] = w;
index++;
}while(w >= 0);
t = 0;
for(i = 0;i < ((sizeof(list)/sizeof(list[0]))+1);i++)
{
sum =0;
if(sum <= 50)
{sum += list[i];}
else
{t++;}
}
printf("%d",t);
return 0;
}

I get a segmentation error on my do while loop
The first segmentation fault happens at this line:
list[index] = w;
What do you think is the value of index?
You did not initialize it with a value, which probably should have been 0.
Therefore, accessing list[index] is undefined behaviour. In your case, it caused a segmentation fault.
Then inside for(i = 0;i < ((sizeof(list)/sizeof(list[0]))+1);i++)
Accessing list[i] here can cause another segfault at the final value of i. You should remove the +1 from ((sizeof(list)/sizeof(list[0]))+1).
Solution:
Do index = 0; once (initialization) before doing list[index] = w;
Remove the +1 from ((sizeof(list)/sizeof(list[0]))+1)
But it would be better to change
for(i = 0;i < ((sizeof(list)/sizeof(list[0])));i++) to
for (i = 0; i < 15; ++i)
Because you already know the size of your list and list[15] is guaranteed to be -1 if there are 15 weights. So, you just need to traverse upto list[14].
This just removes the segfault, but there are still other problems in your code.
I want to know why code is not working and then solve the question on
my own.
The logic inside your for-loop is wrong.
sum =0;
if(sum <= 50)
This condition is always true, and your else block which increments the value of t is never executed. Therefore, the output is always the initial value which you assign to t.

first you have used an uninitialized variable index use index=0.
also as question said a maximum of 15 different , but you are using ((sizeof(list)/sizeof(list[0]))+1) which aside from +1 at the end of it ,which will cause passing boundaries of your array which will lead to undefined behavior, is wrong , because you will traverse array completely while it's possible that you have less elements in array. you should add a counter while you are scanning data and your second loop should be based on that.
also your code is different from question , if input is always 0 < input <= 50 you will never enter else statement(t++) and you will always print 0. you are finding sum of weights and not count of them , and with the input explained in question you will always print t=0.

Related

How do I find the number of element of an array which have their size previously undefined

I'm trying to make an array which have it's element coming from a user input. This array would first have it's size undefined since we don't know how much int would the user input, but then I'm not able to find the amount of element in the array like this unless I put a counter on the loop function.
Here is the code that I've made:
int cross[] = {0};
int k;
for (k = 0; k >= 0; k++){
scanf("%d", &cross[k]);
if (cross[k] == -1){
break; //stop the user from inputing numbers if user input -1
}
int p = sizeof(cross) / sizeof(cross[0]);
If I were to do printf("%d", p), it would always give me 1 as a result. I'm wondering if there is any other way of doing this other than putting a counter on the for loop.
Thanks!!
This phrase from your question is both wrong and dangerous: "This array would first have it's size undefined".
The following line of code defines a fixed-size array that has exactly one element:
int cross[] = {0};
The compiler knows it's one element because you supplied one initializer value {0}. If you supplied this {0, 5, 2}, it would allocate 3 integers, and so on.
This means when you store into cross[k] and k is larger than zero, you're actually exceeding the bounds of your allocated array, which C doesn't catch at compile time, but could cause nasty problems at run time.

int variable changes to 1 after 'while' loop

I was trying to make a 'decimal to binary' program. It should convert from 0 to 255 only and it does.
I have two variables, 'n' and 'temp', when the user first enters the number I store it on 'n'. Then I assign 'n' to 'temp' (thus creating a copy, at least that's what I think I'm doing).
then I only use 'temp' in my code. I never use 'n', not until the end where I decide to print the number the user entered. And here comes the problem, if I enter a number greater than 255, the variable 'n' changes to 1.
I tried running my code through a couple C online compilers and all of them output the variable 'n' the right way, meaning that despite the binary not working when the numbers is greater than 255 (as intended) they print the entered value.
I found one online compiler where it doesn't print the 'n' variable if its greater than 255.
https://www.tutorialspoint.com/compile_c_online.php
If you run my code through this compiler, you'll see how the variable 'n' changes to 1 without it being used.
I know the 'binary part' won't work if you use a number greater than 255. I want to know why 'n' changes out of nowhere.
#include <stdio.h>
int main()
{
int bin[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int arrSize = 7;
int n;
int temp;
scanf("%d", &n);
temp = n;
while(temp != 0)
{
bin[arrSize] = temp % 2;
temp = temp / 2;
arrSize = arrSize - 1;
}
printf(" Decimal: %d ----> binary: ", n);
for(int i = 0; i <= 7; i++)
{
printf("%d", bin[i]);
}
printf("\n");
return 0;
}
You've run through a "Buffer overflow".
A quick definition for that:
A buffer overflow occurs when a program or process attempts to write
more data to a fixed length block of memory, or buffer, than the
buffer is allocated to hold. Since buffers are created to contain a
defined amount of data, the extra data can overwrite data values in
memory addresses adjacent to the destination buffer unless the program
includes sufficient bounds checking to flag or discard data when too
much is sent to a memory buffer.
The error in your code remains in this while loop:
while(temp != 0){
//I added this line to make it clear
printf("inside loop\tarrSize=%d\n",arrSize);
bin[arrSize] = temp % 2;
temp = temp / 2;
arrSize = arrSize - 1;
}
For an input equals to 300 (The error will occur for each input > 255) you'll have this output:
inside loop arrSize=7
inside loop arrSize=6
inside loop arrSize=5
inside loop arrSize=4
inside loop arrSize=3
inside loop arrSize=2
inside loop arrSize=1
inside loop arrSize=0
inside loop arrSize=-1
inside loop arrSize=0
The problem is that we have an index equals to -1, You'll ask what will happen ? well in fact arrays are pointers to the address of the first element of the table + the offset (index * size of the type of the table) which means that for bin[-1] it is in fact arrSize, and bin[-2] is in fact n.
You can check this by verifying the addresses as it follows:
printf("# of bin[-1]:\t%p\n",(void*)&bin[-1]);
printf("# of arrSize:\t%p\n\n",(void*)&arrSize);
printf("# of bin[-2]:\t%p\n",(void*)&bin[-2]);
printf("# of n:\t\t\t%p\n",(void*)&n);
which with my compiler gave me:
# of bin[-1]: 0x7ffe00e32f9c
# of arrSize: 0x7ffe00e32f9c
# of bin[-2]: 0x7ffe00e32f98
# of n: 0x7ffe00e32f98
So you changes without knowing bin[-1] (or bin[-2] according to the value of n) which is in fact arrSize (or n)..
How you can fix this ? I advice you to verify the index every time you want to loop over an array (the condition of the loop must be in function of arrSize). Or you can if you want for this specific exemple to ignore that and focus on the logic: verify the input (in your case the input n must be: 0 <= n <= 255)
void *ieee2b(double value,char size,void *res){
char
*p0=res,
*p=p0;
vbreplacec(vbsprintf(p,"%*.*s",size,size," "),' ','0',p);
if((long)value!=value)
while(1){
double
tmp=value*2;
*p++='0'+(long)tmp;
if(tmp==1||tmp==0||p-p0>size)
break;
value=tmp-(long)tmp;
}
else{
p=p0+size-1;
while((long)value>1){
*p--='0'+((long)value%2);
value=(long)value/2;
}
*p--='0'+((long)value);
}
return res;
}

Why am I getting this output from printing the contents of an array with only 17 bytes?

I am working through CS50 on edX and have reached the problem where you have to do a checksum for credit card numbers.I am new to programming and even newer to C.
I am collecting the digits in arrays so I can manipulate them.
I have collected every other digit from the original number and multiplied this by two.
When I try to print this collection I get the digits I want initially but then a dash and whole load of other numbers - I have no idea where these are coming from?
// establishing another array to collect the doubled digits of every other digit from the first array
int doubledDigs[16];
int k = 0;
// building that array, ensuring to split any multi digit products and add them idnividually
for (int i = 0; i<= 15; i += 2, k++)
{
int a = collector[i] * 2;
if (a > 9)
{
for (int c=0; c < 2; c++, k++)
{
int b = a % 10;
doubledDigs[k] = b;
a = floor(a / 10);
}
}
doubledDigs[k] = a;
}
// print doubledDigs to check it is working
for (int i = 0; i <= 15; i++)
{
int b = doubledDigs[i];
printf ("%i", b);
}
printf ("\n");
//add all the doubled digits together
int doubledProduct = 0;
for (int i=0; i <= 15; i++)
{
doubledProduct += doubledDigs[i];
}
//print product to check
printf("%i\n", doubledProduct);
So if input 1234567890123 as my card number I get 62810410010620-74895702432659
-748924334
as an output.The first 14 digits are correct and the ones that I want - but where are all these other numbers coming from?
You're getting this output because of one of two things: either you're accessing your collector array out of its bounds, or you're failing to initialize the last few members of that array, resulting in garbage data being accessed.
Your algorithm assumes that collector and doubledDigs have the same number of members, but since your code doesn't include the part where you declare that array, it's unclear if that is true or not.
Assuming they are the same size, if you're filling collector with the input "1234567890123", then you're leaving 3 uninitialized members. In C, if you do not explicitly set the value of a variable or array member, its initial value is equal to whatever happens to be in memory at that particular location. For a signed int, that can be anywhere between 2,147,483,647 and -2,147,483,648.
To guard against this, the first thing you may want to do is zero-initialize your array using int collector[16] = {0};.
That only fixes things in the case that collector and doubledDigs are supposed to be the same size. If it's intended that collector has 14 members and doubledDigs has 16, for instance, you will have to revisit your loop logic. In that example, in the last 2 iterations of the loop, you will attempt access the 15th and 16th members of collector, which don't exist. C will not stop you from doing this, but the result is undefined behavior at best.

My C program outputs undesired array values [closed]

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've been tasked to code a program that processes a simple 1D array to return its element values, but the compiler has been behaving strangely; outputting more values than I have array elements.. It's also not being fully compliant with one of my statements (one that prints a new line character every 8 elements) and not assigning the largest value to my variable. I think that the other two problems will go away once the first problem is fixed, however.
Here is my brief:
Design, code and test a program that:
Fills a 20 element array (marks) with random numbers between 0 and 100.
Prints the numbers out 8 to a line
Prints out the biggest number, the smallest number and the average of the numbers
And here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
srand(time(NULL));
int marks[20];
int i = 0;
int sum = 0;
int min;
int max;
for(i;i<=sizeof(marks);i ++){
marks[i] = rand() % 100;
sum += marks[i];
if(i % 8 == 0){
printf("\n");
}
printf("%d ", marks[i]);
if(marks[i]>max){
max = marks[i];
}
else if(marks[i]<min){
min = marks[i];
}
}
printf("\n\nThe minimum value is: %d", min);
printf("\nThe maximum value is: %d", max);
printf("\n\nThe average value is: %d", sum / sizeof(marks));
return 0;
}
Please can someone help me get the correct output?
sizeof() function returns the byte length of the array, so this code "thinks" your array is 20 * whatever byte size ints are on your machine. You will want to just use i < 20 in the loop or go
for (i;i<sizeof(marks)/sizeof(int); i ++) { ...
Note that you probably do not want the <= operator in the for loop, since arrays are 0 indexed, thus marks[20] is actually one beyond the array.
There are two problem I can see that will invoke undefined behavior in your code.
By saying for(i;i<=sizeof(marks);i ++), you're out of bounds.
int min; int max; are not initialized and you're attempting to use it.
to solve this.
Change the for loop condition to for(i; i< 20; i++). Better to use a preprocessor construct like #define SIZ 20 and then make use of it accross your code to make it consistent and robust.
Initialize your local variables. max should be INT_MIN, and min can be INT_MAX. (see limits.h for reference).
To clarify more on point 2, max and min are automatic local variables, and in case not initialized explicitly, it contains indeterminate values.
C11, chapter §6.7.9,
If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate.
and then, directly from the Aneex J, §J.2, Undefined behaviour,
The value of an object with automatic storage duration is used while it is
indeterminate.
if(marks[i]>max){
max = marks[i];
}
else if(marks[i]<min){
min = marks[i];
}
min and max are not initialized here. Make sure to set your compiler warnings at the highest level, so you get a warning message when you forget to initialize variables.
for(i;i<=sizeof(marks);i ++){
This doesn't make sense. Replace sizeof(marks) with the number of times you want to loop, and use < instead of <=.
For example:
const int num_marks = 20; // or use #define
int marks[num_marks];
for(i = 0; i < num_marks; i++) {}

What part of this causes a floating point exception?

I would be most grateful if people could have a look over this snippet of code and let me know what could a possible cause for the floating point exception.
Info:
branches is an int array size 200
line is a char array size 20
The loop runs fine 6 times, then the exception occurs.
I am confused because there is no division, float or integer, that could cause this.
for (count = 0; count < sizeof(branches); count++){
if (fgets(line,sizeof(line),fp)==NULL)
break;
else {
int branch_taken = line[16] - 48;
branches[count] = branch_taken;
}
}
sizeof(branches) is a size in bytes - you need to use a constant which represents the number of elements i.e. 200, otherwise you will be exceeding the bounds of your branches array, which will result in Undefined Behaviour.
Your code should probably look something like this:
#define NUM_BRANCHES 200
int branches[NUM_BRANCHES];
for (count = 0; count < NUM_BRANCHES; count++)
{
...

Resources