0

first time posting. I swear I looked for answers in other segmentation fault questions already, but I am new to programming and to troubleshooting/researching effectively.

My PSet1 program "Credit" compiles and it properly handles every single check in check50... except for two similar cases. I get "Segmentation fault" when I input the credit card # 4222222222222 and 4222222222223. Why does this happen?

Full code is below. I imagine my code is not efficient and the notes are more for my benefit than yours, but it's what I got so far:

#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <math.h>

int main(void)
{

    long cc_number = get_long("Number: ");
    int cc_length = floor(log10(labs(cc_number)));
    long number = cc_number;
    int arr[cc_length];

    //write the credit card number as an array starting from the end using remainders
    for (int i = cc_length; i >= 0; i--)
    {
        arr[i] = number % 10;
        number = number / 10;
    }

    //perform Luhn's algorithm
    int sum = 0;

    //starting with 2nd-to-last digit in array, double each value
    for (int i = cc_length - 1; i >= 0;)
    {
        int checksum_add = arr[i] * 2;
        //if doubled value is 10 or greater, add it's digits together (which is the same as subtracting 9)
        if (checksum_add > 9)
        {
            sum = sum + checksum_add - 9;
        }
        else
        //if it is not 10 or greater, just add the value
        {
            sum = sum + checksum_add;
        }
        //decrement to get every other digit in array
        i = i - 2;
    }
    // now add up all remaining digits' values
    for (int i = cc_length; i >= 0;)
    {
        sum = sum + arr[i];
        i = i - 2;
    }
    //perform checks for various credit cards based on length, first digit(s), and Luhn's algorithm result
    if (cc_length == 14 && arr[0] == 3 &&  (arr[1] == 4 || arr[1] == 7) && sum % 10 == 0)
    {
        printf("AMEX\n");
    }
    else if (cc_length == 15 && arr[0] == 5 && arr[1] > 0 && arr[1] < 6 && sum % 10 == 0)
    {
        printf("MASTERCARD\n");
    }
    else if ((cc_length == 12 || cc_length ==15) && arr[0] == 4  && sum % 10 == 0)
    {
        printf("VISA\n");
    }
    else
    {
        printf("INVALID\n");
    }
}

Results for cs50/problems/2021/x/credit generated by check50 v3.3.0

:) credit.c exists

:) credit.c compiles

:) identifies 378282246310005 as AMEX

:) identifies 371449635398431 as AMEX

:) identifies 5555555555554444 as MASTERCARD

:) identifies 5105105105105100 as MASTERCARD

:) identifies 4111111111111111 as VISA

:) identifies 4012888888881881 as VISA

:( identifies 4222222222222 as VISA

expected "VISA\n", not ""

:) identifies 1234567890 as INVALID

:) identifies 369421438430814 as INVALID

:) identifies 4062901840 as INVALID

:) identifies 5673598276138003 as INVALID

:) identifies 4111111111111113 as INVALID

:( identifies 4222222222223 as INVALID

expected "INVALID\n", not ""

To see the results in your browser go to https://submit.cs50.io/check50/82b01a7344c69be463d9660c64e599d081445fbe

1

The code is not counting the number of digits correctly. It's generating counts that are one less than the actual length. You can verify this by inserting printf("cc_length = %i\n",cc_length); after the length is calculated.

This is the root cause of the seg fault. Here's how. The number of elements in the array int arr[cc_length]; are one less than needed. Say that the credit card number length is 13. cc_length will be 12, so arr[] will have 12 elements. Later code will assign something to arr[12], for which there is no space allocated, but it will still happen. That means that whatever is next in physical memory will be overwritten with that write. This is what's corrupting data. Sometimes, it'll throw a seg fault, other times it won't.

You can eliminate the seg fault by increasing the size allocated to arr[] by 1, like this, int arr[cc_length+1]; to debug, but you should really fix the calculation of the length.

This software bug has a lot of ramifications. It makes me wonder how the code can find other numbers to be valid CC numbers if the length is wrong. I suspect that fixing this is going to reveal other problems that are being masked. You should be on the lookout for false positives most of all.

If you have questions about other issues in this code, please post a new question. ;-)

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

2
  • Wow - I was fundamentally misunderstanding setting up an array vs. assigning values to a location in an array. Thank you!
    – oms_CS50
    Jun 26 at 0:56
  • I forgot to remind this. The first element of an array is array[0], not array[1].
    – Cliff B
    Jun 26 at 0:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .