堆栈溢出问题:最大容量 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?
本质上,我写了一个相当小的随机字符生成器,用户可以在其中选择字符串的长度。该程序可以成功创建一个长度为 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?