Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
261 views
in Technique[技术] by (71.8m points)

c - My program runs correctly while debugging, but incorrectly when out of debugging

I'm currently in the middle of writing a simple program in C that takes a command line argument from the user that is a substitution cipher key. Currently, my program is checking for all the possible incorrect arguments the user might enter.

Running this through the debugger results in my program running perfectly every single time, no matter what the input is. However, running my program without the debugger, while also making the argument have at least one lower-case letter (eg. ./substitution VCHPRZGJNTLSKFBDQWAXEuymoi), results in the 'sum' variable having an incorrect value about 50% of the time.

I'll quickly explain what the 'sum' variable is for just so it's easier to understand. 'sum' starts out at 2015, because that's the value of adding up all 26 upper case letters according to the ASCII table. The for loop in my function then subtracts from 2015 each character from the cipher key. Finally, the last if statement checks for whether sum = 0, meaning that only unique characters were entered.

When running this without a debugger, 'sum' is sometimes 0 and sometimes -32 * the number of lower-case letters. For example, VCHPRZGJNTLSKFBDQWAXEuymoi has 4 lower-case letters, and 'sum' is sometimes 0 and sometimes -128.

I've got no idea where this problem is coming from, and I would greatly appreciate any help.

Here is my code:

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

string sub(string plaintext,string cipher);

int main(int argc, string argv[])
{
    string cipher = argv[1];
    // checks for whether an argument was provided
    if (argc != 2)
    {
        printf("Usage: ./substitution KEY
");
        return 1;
    }
    // checks for whether the cipher is 26 characters long
    else if (strlen(cipher) != 26)
    {
        printf("Key must contain 26 characters
");
        return 1;
    }
    
    // makes sure the cipher contains only non-alphabetical characters
    // also subtracts from 2015 (sum of all unique, upper-case letters) with each iteration to test for whether every character in the argument is unique
    int sum = 2015;
    for (int i = 0; i < strlen(cipher); i++)
    {
        if ((int) cipher[i] > 96 && (int) cipher < 123)
        {
            cipher[i] = (char) ((int) cipher[i] - 32);
        }
        
        if ((int) cipher[i] < 65 || ((int) cipher[i] > 90 && (int) cipher[i] < 97) || (int) cipher[i] > 122)
        {
            printf("Key must only contain alphabetical characters.
");
            return 1;
            break;
        }
        sum -= ((int) cipher[i]);
    }
    
    // DEBUG: prints 'sum'
    printf("%i
", sum);
    
    // THIS IS THE PROBLEM STATEMENT
    // determines whether every character in the argument is unique
    if (sum != 0)
    {   
        printf("Key must contain all unique characters.
");
        return 1;
    }
    
    // gets the plaintext from the user and prints out the cipher text using the 'sub' function
    string plaintext = get_string("plaintext: ");
    printf("ciphertext: %s
",sub(plaintext,cipher));
}
question from:https://stackoverflow.com/questions/65852850/my-program-runs-correctly-while-debugging-but-incorrectly-when-out-of-debugging

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your OS is probably using ASLR for preventing exploitation of memory corruption vulnerabilities. This might be the reason why the value of the sum variable has an incorrect value about 50% of the time. As spotted in this comment a pointer is compared to an integer in if ((int) cipher[i] > 96 && (int) cipher < 123), which might be the problem. However, ASLR seems to get disabled by your debugger and the addresses get not randomized. Therefore, the address pointed by the variable cipher is not randomized and you always get the same result.

If you are using gdb you can enable ASLR with the command set disable-randomization off.

Edit As suggested by Eric Postpischil in his comments [1, 2] you should use 'a' instead of constants like 97 and the (int) casts should be entirely removed. The (int) casts are unnecessary, since the char elements of the array will be promoted to int.

You should also see the compiler warnings.

For

if ((int) cipher[i] > 96 && (int) cipher < 123)

I get the following warning:

warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
if ((int) cipher[i] > 96 && (int) cipher < 123) {

On gcc -Wpointer-to-int-cast should be enabled by default. Otherwise, you can also also try the -Wall option.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...