2013-01-05 15 views
2

對於包含as,bs和cs的字符串,我們可以執行以下操作。我們可以將任何兩個相鄰的不同字符替換爲第三個字符。例如,'ab'變成'c','ba'變成''等等。我寫這個代碼,以執行上噸串以下操作(噸< = 100)和字符串的最大長度= 100在完美運行的程序中檢測到緩衝區溢出(顯然)

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

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) 

它在所有情況下不完全相同,但幾乎相同。請幫忙。

回答

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

千萬不要使用gets函數。在這種情況下,如果它收到超過3個字符(包括終止空字符),則會發生緩衝區溢出。

gets已在當前標準(C11)中刪除並在之前的標準(C99)中不再使用。

+2

超過兩個字符也是不好的,因爲'gets'會自動附加終止空字符。 – Zeta

+0

@Zeta我加了一個關於空字符的精度。 – ouah

1

代碼可能輸入了一個100個字符的字符串,這需要101個字節來存儲(包括最後的NUL字節)! 另外,從來沒有,從來沒有在任何代碼中使用gets()函數是強大的。嘗試getline(),它會自動爲您擴展緩衝區。

此外,通過這樣的回溯,您可以使用addr2line來解碼地址。編譯爲-g-rdynamic

0

char r[3]; 
gets(r); 

極有可能打破超過2個字符加上一個換行符任何輸入。請注意,由於緩衝區溢出問題,gets由C標準正式廢棄。這些天來,我們使用沿着

char r[42]; 

if (fgets (r, sizeof r, stdin) != NULL) { ... } 

是溢出安全的東西(它,而截斷輸入和離開休息下一個fgets)。