【问题标题】:Program crashes程序崩溃
【发布时间】:2016-09-16 19:27:56
【问题描述】:

我正在尝试编写代码来检查大写字母的密码。 当我输入带有大写字母的密码时,程序按预期运行(打印出“1”和输入的密码)。 但是,如果我输入的密码没有大写字母,程序就会崩溃。

我的代码:

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

int main() {

    char password[100];
    int i = 0;
    int upper = 0;

    printf("Enter a password with an uppercase letter: ");
    scanf("%s", password);

    for (i = 0; i <= 100; i++) {
        if (isupper(password[i])) {
            upper = 1;
            break;
        }
    }

    printf("%d\n", upper);
    printf("%s\n", password);

    system("pause");
    return (0);
}

错误:

调试断言失败!

程序: ...15\Projects\ConsoleApplication3\Debug\ConsoleApplication3.exe 文件: minkernel\crts\ucrt\src\appcrt\convert\isctype.cpp 行:36

表达式:c >= -1 && c

有关您的程序如何导致断言失败的信息, 请参阅有关断言的 Visual C++ 文档。

(按重试调试应用程序)ConsoleApplication3.exe 有 触发断点。

调试断言失败!

程序: ...15\Projects\ConsoleApplication3\Debug\ConsoleApplication3.exe 文件: minkernel\crts\ucrt\src\appcrt\convert\isctype.cpp 行:42

表达式:c >= -1 && c

有关您的程序如何导致断言失败的信息, 请参阅有关断言的 Visual C++ 文档。

(按重试调试应用程序)ConsoleApplication3.exe 有 触发断点。

程序“[13188] ConsoleApplication3.exe”已退出,代码为 0 (0x0)。

【问题讨论】:

  • 您有一个 100 个字符的数组,但您正在访问第 101 个字符。您也可能超出输入的字符串,因为您不检查字符串终止符,从而访问未初始化的内存。最后,您对输入没有任何限制,这意味着用户可能会向您的数组写入 100 多个字符。所有这些问题都会导致未定义的行为
  • 您可以在遇到的第一个空字符处停下来。但这个消息很有趣。 c &gt;= -1 &amp;&amp; c &lt;= 255 怎么会因为一个字符而失败?
  • 并且该数组中未被scanf 填充的部分未初始化,因此检查其值是毫无价值的。
  • @RawN:这显然是编译成C++代码,所以C++标签正确,C标签错误!
  • @Jean-FrançoisFabre:下限确实应该是c &gt; -1 resp。 c &gt;=0。但isupper 似乎只为标准字符集代码定义。并在 x86/Windows char 上签名。

标签: c++ debugging visual-studio-2015


【解决方案1】:

改变这个:

for (i = 0; i <= 100; i++) {

for (i = 0; i < 100 && password[i] != '\0'; i++) {
              ^^^      ^^^^^^^^^^^^^^^^^^
        note: no =     check for end of string

你有

char password[100];

所以合法索引只有 0 到 99。此外,您需要检查是否已到达字符串结尾(也称为密码 [I] != '\0')

一种更好的方式来做你想做的事情(灵感来自@Jean-Francois Fabre):

     scanf("%99s", password);
             ^^
             To prevent buffer overflow

     for (i = 0; i < strlen(password); i++) {
         ....

【讨论】:

  • 正确的循环会在第一个 NULL 字符处停止,而不是一直到 100。
  • 此更改已解决问题(谢谢!),但我不明白为什么。
  • @Eden 1) 因为你不能访问密码[100] 和 2) 如果输入少于 100 个字符,你必须在输入字符串结束时停止。
  • 并像这样扫描:scanf("%99s", password); 以避免缓冲区溢出和对您的超级安全代码的恶意攻击:)
  • @Jean-FrançoisFabre - 正确 - 答案也随该部分更新。谢谢。
【解决方案2】:

改变:

for (i = 0; i <= 100; i++) 

到:

for (i = 0; i < strlen(password); i++)

注意:如果没有大写字母,则超出范围。

【讨论】:

  • 这是问题所在,是的。但是回答同样的事情没有意义(但稍微差一点,因为strlen 在每次迭代时都会运行字符串)而不是当前正确的现有答案。
猜你喜欢
  • 1970-01-01
  • 2013-05-30
  • 2011-10-16
  • 2020-03-14
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多