是否有可能以某种方式使该程序崩溃?

Mr.*_*ose 2 c memory arrays string crash

我目前正在大学的一门课程中学习 C。现在我们有一个任务要解决,我不知道该怎么做。

任务看起来像这样:“是否有可能让这个程序因用户输入而崩溃?如果是这样,请解释这种情况。”

我们得到的程序非常简单,如下所示:

#include <stdio.h>  // Include to use printf, scanf

int main()
{
    // Define buffers to store user name and password
    char username[16];
    char password[16];

    // Read username and password from user input
    printf("Enter your name: ");
    scanf("%s", username);
    printf("Enter your password: ");
    scanf("%s", password);
    printf("[SHOUTING OUT LOUD] Hello, %s!\n", username);

    return 0;
}   
Run Code Online (Sandbox Code Playgroud)

我已经发现,如果您使用超过 15 个字符的用户名,您可以让程序打印出密码。但这显然不是崩溃。所以我还没有找到使程序崩溃的方法,但不知何故我很确定,有一种方法可以做到这一点。有人有什么想法吗?

谢谢 :)

dbu*_*ush 6

输入用户名或密码超过15个字符可以引起程序崩溃,它只是不能保证这样做。

当你写越过数组的边界时,你会调用undefined behavior。粗略地说,这意味着您不能对您的程序将做什么做出任何假设。它可能会崩溃,可能会输出奇怪的结果,或者可能看起来工作正常。

仅仅因为程序可能崩溃并不一定意味着它崩溃。


话虽如此,鉴于您可能遇到的大多数编译器的工作方式,您输入的字符串越长,您就越有可能发生崩溃。

局部变量通常在彼此相邻的堆栈上分配。例如,假设就在堆栈username之前password。如果你在一个20字符的名称作为用户名进入,它会写过去username进入passwordusername将不包含空值终止字节。当您输入密码时,它会覆盖用户名的前 16 个字符之后的任何字符。然后当您打印时username,您将看到您输入的前 16 个字符,然后是密码。

现在假设您输入 100 个字符作为用户名。这将写入过去username和过去,password并且很可能会覆盖main. 然后当main试图返回时读取一个虚假地址,并试图跳转到该地址是导致崩溃的原因。

但同样,这都是非常特定于系统的,并且可能会根据您放置变量的类型/顺序、您调用的函数以及您用于编译的优化设置等而有所不同。

  • @RobertSsupportsMonicaCellio,不,不会。数组后面可能有未使用的内存可以写入。虽然非法,但在这种情况下它不会使程序崩溃。 (3认同)
  • @RobertSsupportsMonicaCellio OP 说“我已经发现,如果您使用的用户名长度超过 15 个字符,您可以让程序打印出密码”。这是一个明显的例子,说明即使缓冲区溢出也不会崩溃的情况。 (2认同)