我的程序在调试时运行正确,但在调试结束时运行不正确
My program runs correctly while debugging, but incorrectly when out of debugging
我目前正在用 C 编写一个简单的程序,该程序从用户那里获取一个命令行参数,即替换密码密钥。目前,我的程序正在检查用户可能输入的所有可能不正确的参数。
运行 通过调试器,无论输入是什么,我的程序每次都运行 完美无缺。但是,运行 我的程序没有调试器,同时还使参数至少有一个小写字母(例如 ./substitution VCHPRZGJNTLSKFBDQWAXEuymoi),导致 'sum' 变量的值不正确,约为 50 % 的时间。
我将快速解释 'sum' 变量的用途,以便于理解。 'sum' 从 2015 开始,因为这是根据 ASCII table 将所有 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));
}
您的 OS 可能正在使用 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 注释将指针与 if ((int) cipher[i] > 96 && (int) cipher < 123)
中的整数进行比较,这可能是问题所在。
但是,ASLR 似乎被您的调试器禁用并且地址未随机化。因此,变量 cipher
指向的地址不是随机的,你总是得到相同的结果。
如果您使用的是gdb
,您可以使用命令set disable-randomization off
启用ASLR。
编辑
正如 Eric Postpischil 在他的评论 [, ] 中所建议的那样,您应该使用 'a' 而不是像 97 这样的常量,并且应该完全删除 (int) 强制转换。 (int) 转换是不必要的,因为数组的 char
元素将被提升为 int
.
您还应该看到编译器警告。
对于
if ((int) cipher[i] > 96 && (int) cipher < 123)
我收到以下警告:
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
应默认启用。否则,您也可以尝试 -Wall 选项。
无关,但对于这种比较,有 ctype.h
这会将循环更改为
for (int i = 0; i < strlen(cipher); i++)
{
if (islower(cipher[i]))
{
cipher[i] = toupper(cipher[i]);
}
if (!isalpha(cipher[i]))
{
printf("Key must only contain alphabetical characters.\n");
return 1;
/* break; */
}
sum -= (int) cipher[i];
}
这将减少代码长度,使代码更具可读性,避免常量,并避免一些陷阱。
还有一点,这里不需要 break
,因为你已经从函数中 return
。所以永远不会达到中断。
我目前正在用 C 编写一个简单的程序,该程序从用户那里获取一个命令行参数,即替换密码密钥。目前,我的程序正在检查用户可能输入的所有可能不正确的参数。
运行 通过调试器,无论输入是什么,我的程序每次都运行 完美无缺。但是,运行 我的程序没有调试器,同时还使参数至少有一个小写字母(例如 ./substitution VCHPRZGJNTLSKFBDQWAXEuymoi),导致 'sum' 变量的值不正确,约为 50 % 的时间。
我将快速解释 'sum' 变量的用途,以便于理解。 'sum' 从 2015 开始,因为这是根据 ASCII table 将所有 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));
}
您的 OS 可能正在使用 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 if ((int) cipher[i] > 96 && (int) cipher < 123)
中的整数进行比较,这可能是问题所在。
但是,ASLR 似乎被您的调试器禁用并且地址未随机化。因此,变量 cipher
指向的地址不是随机的,你总是得到相同的结果。
如果您使用的是gdb
,您可以使用命令set disable-randomization off
启用ASLR。
编辑
正如 Eric Postpischil 在他的评论 [char
元素将被提升为 int
.
您还应该看到编译器警告。
对于
if ((int) cipher[i] > 96 && (int) cipher < 123)
我收到以下警告:
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
应默认启用。否则,您也可以尝试 -Wall 选项。
无关,但对于这种比较,有 ctype.h
这会将循环更改为
for (int i = 0; i < strlen(cipher); i++)
{
if (islower(cipher[i]))
{
cipher[i] = toupper(cipher[i]);
}
if (!isalpha(cipher[i]))
{
printf("Key must only contain alphabetical characters.\n");
return 1;
/* break; */
}
sum -= (int) cipher[i];
}
这将减少代码长度,使代码更具可读性,避免常量,并避免一些陷阱。
还有一点,这里不需要 break
,因为你已经从函数中 return
。所以永远不会达到中断。