我的程序在调试时运行正常,但在调试时运行不正确

bmo*_*zov 2 c debugging caesar-cipher cs50

我目前正在用 C 编写一个简单的程序,该程序从用户那里获取一个命令行参数,该参数是一个替换密码密钥。目前,我的程序正在检查用户可能输入的所有可能不正确的参数。

无论输入是什么,通过调试器运行它都会使我的程序每次都完美运行。但是,在没有调试器的情况下运行我的程序,同时使参数至少有一个小写字母(例如 ./substitution VCHPRZGJNTLSKFBDQWAXEuymoi),会导致“sum”变量在大约 50% 的情况下具有不正确的值。

我将快速解释“sum”变量的用途,以便更容易理解。'sum' 从 2015 年开始,因为这是根据 ASCII 表将所有 26 个大写字母相加的值。我的函数中的 for 循环然后从 2015 中减去密码密钥中的每个字符。最后,最后一个 if 语句检查 sum = 0,这意味着只输入了唯一字符。

在没有调试器的情况下运行它时,'sum' 有时是 0,有时是 -32 * 小写字母的数量。例如,VCHPRZGJNTLSKFBDQWAXEuymoi 有 4 个小写字母,'sum' 有时为 0,有时为 -128。

我不知道这个问题是从哪里来的,我将不胜感激任何帮助。

这是我的代码:

#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\n");
        return 1;
    }
    // checks for whether the cipher is 26 characters long
    else if (strlen(cipher) != 26)
    {
        printf("Key must contain 26 characters\n");
        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.\n");
            return 1;
            break;
        }
        sum -= ((int) cipher[i]);
    }
    
    // DEBUG: prints 'sum'
    printf("%i\n", 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.\n");
        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\n",sub(plaintext,cipher));
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*nio 5

您的操作系统可能正在使用ASLR来防止利用内存损坏漏洞。这可能是sum变量值在大约 50% 的时间具有不正确值的原因。正如在评论中发现的那样,将指针与 中的整数进行比较if ((int) cipher[i] > 96 && (int) cipher < 123),这可能是问题所在。但是,您的调试器似乎禁用了 ASLR,并且地址未随机化。因此,变量指向的地址cipher不是随机的,你总是得到相同的结果。

如果您正在使用,gdb您可以使用命令启用 ASLR set disable-randomization off

编辑 正如 Eric Postpischil 在他的评论 [ 1 , 2 ] 中所建议的那样,您应该使用 'a' 而不是像 97 这样的常量,并且应该完全删除 (int) 类型转换。(int) 强制转换是不必要的,因为char数组的元素将被提升为int.

您还应该看到编译器警告。

为了

if ((int) cipher[i] > 96 && (int) cipher < 123)
Run Code Online (Sandbox Code Playgroud)

我收到以下警告:

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

gcc -Wpointer-to-int-cast默认情况下应启用。否则,您也可以尝试使用-Wall选项。