堆栈溢出问题:最大容量 2,077,072

Stack overflow issue: max capacity 2,077,072

本质上,我写了一个相当小的随机字符生成器,​​用户可以在其中选择字符串的长度。该程序可以成功创建一个长度为 2,077,072 的字符串,但在大于 1 时因堆栈溢出而崩溃。

这个数字似乎相当随意,因为 log2(thatNumber) 大约等于 20.9。它太小,不能超过 2 兆字节,而且 16 位和 32 位大小都相去甚远。为什么它在所有地方都坏了?

程序至少执行到 "Processing..." 标记。

我的代码:

#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char getChar(int, int, int);

//MAXIMUM PASSWORD LENGTH: 2,077,072
//2,077,073 gives stack overflow

int main(int argc, char **argv) {
    if(argc != 5) {
        printf("Incorrect number of arguments.\n Usage: PassGenII arg1 arg2 arg3 arg4\n");
        printf("arg1: Password length\narg2: Use lowercase characters? 0 or 1\narg3 Use uppercase characters? 0 or 1\narg4: Use numeric characters? 0 or 1\n");
        return 0;
    } else {
        int passLength;
        int lower;
        int upper;
        int numeric;

        passLength = atoi(argv[1]);
        lower = atoi(argv[2]);
        upper = atoi(argv[3]);
        numeric = atoi(argv[4]);

        printf("\nPassword length: %d\n", passLength);
        printf("lowercase: %d\n", lower);
        printf("uppercase: %d\n", upper);
        printf("numerals: %d\n", numeric);
        printf("\nProcessing...");
        char pass[passLength];

        srand(time(NULL));
        int i;
        for(i = 0; i < passLength; i++) {
            pass[i] = getChar(lower, upper, numeric);
        }


        FILE *fp = fopen("C:/PassGen/password.txt", "w");
        for(i = 0; i < passLength; i++) {
            putc(pass[i], fp);
        }
        fclose(fp);

        printf("\n\nSuccessful! The password is in a text file\nin C:/PassGen/\n");

        return 0;
    }
}

char getChar(int lower, int upper, int numeric) {
    int rand1;
    int fail;
    char passChar;

    do {
        fail = 0;
        rand1 = rand() % 3;

        switch(rand1) {
            case 0:
                if(lower) {
                    passChar = rand() % 26 + 97;
                } else {
                    fail = 1;
                }
                break;
            case 1:
                if(upper) {
                    passChar = rand() % 26 + 65;
                } else {
                    fail = 1;
                }
                break;
            case 2:
                if(numeric) {
                    passChar = rand() % 10 + 48;
                } else {
                    fail = 1;
                }
                break;
        }
    } while(fail);

    return passChar;
}

感谢@MOehm,我能够修改代码以取消此限制。新限制现在是 (2^32)/2 - 1,即 2,147,483,647。这更有意义,也比以前大得多。

理论上我可以通过为变量passLength使用比int更大的变量类型来进一步扩展这个限制,但我没有任何真正的理由(而且我会如果我这样做的话,可能最终会有一个 .txt 文件占用我的整个硬盘。

代码修改位:

FILE *fp = fopen("C:/PassGen/password.txt", "w");

int i;
for(i = 0; i < passLength; i++) {
    putc(getChar(lower, upper, numeric), fp);
}

fclose(fp);

我基本上删除了整个存储字符的数组,而是选择将字符直接写入 .txt 文件

char pass[passLength]; 如果您的 passLength 很大,此语句会产生问题。声明巨大的数组从来都不是一个好习惯。

不要声明巨大的数组以避免缓冲区溢出。使用 malloc 来分配巨大的内存。

你可以参考这个How many chars can be in a char array?