在程序中检测到缓冲区溢出,运行完美(显然)

在包含as,bs和cs的字符串上,我们可以执行以下操作。 我们可以取任意两个相邻的不同字符,并用第三个替换它们。 例如,’ab’减少为’c’,’ba’也减少为等等。 我写了这段代码,对t字符串执行以下操作(t <= 100),字符串的最大长度= 100

#include #include #include int redlen(char string[100][100], int x) { int g, checker; checker = 1; for(; checker; ) { checker = 0; for(int i = 0;string[x][i]!='\0'; i++) { if((string[x][i]=='a' && string[x][i+1]=='b') || (string[x][i]=='b' && string[x][i+1]=='a')) { string[x][i]='c'; checker = 1; for(g = i+1; string[x][g]!='\0'; g++) { string[x][g]=string[x][g+1]; } i = 0; } else if((string[x][i]=='b' && string[x][i+1]=='c') || (string[x][i]=='c' && string[x][i+1]=='b')) { string[x][i]='a'; checker = 1; for(g = i+1; string[x][g]!='\0'; g++) { string[x][g]=string[x][g+1]; } i = 0; } else if((string[x][i]=='a' && string[x][i+1]=='c') || (string[x][i]=='c' && string[x][i+1]=='a')) { string[x][i]='b'; checker = 1; for(g = i+1; string[x][g]!='\0'; g++) { string[x][g]=string[x][g+1]; } i = 0; } } } return strlen(string[x]); } void main() { int t; char r[3]; gets(r); t = atoi(r); char string[100][100]; int i; for(i = 0; i<t; i++) { gets(string[i]); } int printval; for(i = 0; i<t; i++) { printval = redlen(string, i); printf("%d",printval); printf(" \n"); } } 

它在问题的示例案例以及我自己开发的案例上都运行良好。 但是当我在网上提交它时,它只通过了十个案例中的一个,而在其他案例中,这个消息突然出现了。

  *** buffer overflow detected ***: /run-DkQcMiKXhWz9LjirrRnu/solution terminated ======= Backtrace: ========= /lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(__fortify_fail+0x45)[0xb76df045] /lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(+0x102e1a)[0xb76dde1a] /lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(__gets_chk+0x165)[0xb76ddd85] /run-DkQcMiKXhWz9LjirrRnu/solution[0x8048436] /lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(__libc_start_main+0xf3)[0xb75f44d3] /run-DkQcMiKXhWz9LjirrRnu/solution[0x80484e9] ======= Memory map: ======== 08048000-08049000 r-xp 00000000 ca:02 15613970 /run-DkQcMiKXhWz9LjirrRnu/solution 08049000-0804a000 r--p 00000000 ca:02 15613970 /run-DkQcMiKXhWz9LjirrRnu/solution 0804a000-0804b000 rw-p 00001000 ca:02 15613970 /run-DkQcMiKXhWz9LjirrRnu/solution 084e2000-08503000 rw-p 00000000 00:00 0 [heap] b75ba000-b75d6000 r-xp 00000000 ca:01 394527 /lib/i386-linux-gnu/libgcc_s.so.1 b75d6000-b75d7000 r--p 0001b000 ca:01 394527 /lib/i386-linux-gnu/libgcc_s.so.1 b75d7000-b75d8000 rw-p 0001c000 ca:01 394527 /lib/i386-linux-gnu/libgcc_s.so.1 b75d8000-b75db000 rw-p 00000000 00:00 0 b75db000-b777e000 r-xp 00000000 ca:01 394522 /lib/i386-linux- gnu/tls/i686/nosegneg/libc-2.15.so b777e000-b777f000 ---p 001a3000 ca:01 394522 /lib/i386-linux-gnu/tls/i686/nosegneg/libc-2.15.so b777f000-b7781000 r--p 001a3000 ca:01 394522 /lib/i386-linux-gnu/tls/i686/nosegneg/libc-2.15.so b7781000-b7782000 rw-p 001a5000 ca:01 394522 /lib/i386-linux-gnu/tls/i686/nosegneg/libc-2.15.so b7782000-b7789000 rw-p 00000000 00:00 0 b7789000-b778a000 r-xp 00000000 00:00 0 [vdso] b778a000-b77aa000 r-xp 00000000 ca:01 400153 /lib/i386-linux-gnu/ld-2.15.so b77aa000-b77ab000 r--p 0001f000 ca:01 400153 /lib/i386-linux-gnu/ld-2.15.so b77ab000-b77ac000 rw-p 00020000 ca:01 400153 /lib/i386-linux-gnu/ld-2.15.so bfe6e000-bfe8f000 rw-p 00000000 00:00 0 [stack] Aborted (core dumped) 

在所有情况下都不完全相同,但几乎相同。 请帮忙。

  int t; char r[3]; gets(r); 

永远不要使用getsfunction。 在这种情况下,如果它收到超过3字符(包括终止空字符),则会出现缓冲区溢出。

已在当前标准(C11)中删除了get,并且在之前的标准(C99)中已弃用。

代码可能输入了一个100个字符的字符串,需要101个字节来存储(包括结尾的NUL字节)! 此外,永远不要在任何意味着健壮的代码中使用gets()函数。 尝试使用getline() ,它会自动为您扩展缓冲区。

此外,通过这些回溯,您可以使用addr2line来解码地址。 使用-g-rdynamic编译。

这个

 char r[3]; gets(r); 

对于超过2个字符加上换行符的任何输入,极有可能中断。 请注意,由于缓冲区溢出问题,get标准已被C标准正式废弃。 这些天我们一直在使用

 char r[42]; if (fgets (r, sizeof r, stdin) != NULL) { ... } 

这是安全的溢出(它相当截断输入,剩下的为下一个fgets )。