Home > other >  Segmentation Fault While Manipulating String
Segmentation Fault While Manipulating String

Time:07-13

I'm trying to create a Ceasar Cipher. For this test, I used a key of 1 and plain text of "hello." When doing so, I get the error message "Segmentation fault (core dumped)". I know this means I am trying to access an illegal memory location, and it's happening while calling the "encrypt" function, but that's all I know.

Depiction of the error I'm getting while debugging.

And here is my code.

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

bool isValidKey(string);
string encrypt(string, int);

string c;

int main(int argc, string argv[])
{
    if (argc != 2 || isValidKey(argv[1]) == 0)
    {
        printf("Useage: ./caesar key\n");
        return 0;
    }
    string p = get_string("plaintext: ");
    c = encrypt(p, atoi(argv[1]));
    printf("%s", c);
    return 0;
}

bool isValidKey(string key)
{
    for (int i = 0; i < strlen(key); i  )
    {
        if (isdigit(key[i]) == 0)
        {
            return false;
        }
    }
    return true;
}

string encrypt(string plain, int k)
{
    for (int i = 0; i < strlen(plain); i  )
    {
        if (isalpha(plain[i]) != 0)
        {
            if (islower(plain[i]) != 0)
            {
                c[i] = ((plain[i] - 97   k) % 26)   97;
            }
            else
            {
                c[i] = ((plain[i] - 65   k) % 26)   65;
            }
        }
    }
    return c;
}

CodePudding user response:

You need to allocate memory for c.

string encrypt(string plain, int k)
{
    c = malloc(strlen(plain)   1);

    for (int i = 0; i < strlen(plain); i  )
    {
        if (isalpha(plain[i]) != 0)
        {
            if (islower(plain[i]) != 0)
            {
                c[i] = ((plain[i] - 97   k) % 26)   97;
            }
            else
            {
                c[i] = ((plain[i] - 65   k) % 26)   65;
            }
        }
    }
    return c;
}

And in main() you should add free(c); before return 0;

CodePudding user response:

The variable c declared in the file scope

string c;

is a null pointer. The above declaration is equivalent to

char *c;

or in fact to

char *c = NULL;

So using the null pointer within the function encrypt like

c[i] = ((plain[i] - 97   k) % 26)   97;

invokes undefined behavior.

Also it is a bad idea when a function like encrypt depends on a global variable.

Also using magic numbers like for example 97 makes the program unclear.

As the function parameter does not have the qualifier const then it will be logical to convert the passed string in place.

Pay attention to that the user can pass a very big integer value as a key. In this case your function will invoke undefined behavior.

So the function can look like

string encrypt( string plain, int k)
{
    k = k % 26;

    for ( size_t i = 0, n = strlen( plain ); i < n; i   )
    {
        if ( isalpha( ( unsigned char )plain[i] ) )
        {
            if ( islower( plain[i] ) )
            {
                plain[i] = ( plain[i] - 'a'   k ) % 26   'a';
            }
            else
            {
                plain[i] = ( plain[i] - 'A'   k ) % 26   'A';
            }
        }
    }

    return plain;
}

The variable c should be removed and in main it is enough to write

string p = get_string( "plaintext: " );
puts( encrypt( p, atoi( argv[1] ) ) );
  • Related