2012-12-21 34 views
-1

我已經用C語言編寫了這段代碼,它適用於小輸入和我能想到的所有測試用例。但是當一個大文件作爲輸入時,它會給出SIGABRT錯誤。有人能解釋我的原因嗎?在C(gcc)代碼中獲取SIGABRT錯誤

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

void q_sort(char **numbers, int left, int right) 
{ 
    int l_hold, r_hold,temp; 
    char *pivot; 

    l_hold = left; 
    r_hold = right; 
    pivot = numbers[left]; 

    while (left < right) 
    { 
     while (strcmp(numbers[right],pivot)>=0 && (left < right)) 
      right--; 

     if (left != right) 
     { 
      numbers[left] = numbers[right]; 
      left++; 
     } 

     while (strcmp(numbers[left],pivot)<0 && (left < right)) 
      left++; 

     if (left != right) 
     { 
      numbers[right] = numbers[left]; 
      right--; 
     } 
    } 

    numbers[left] = pivot; 
    temp = left; 
    left = l_hold; 
    right = r_hold; 

    if (left < temp) 
     q_sort(numbers, left, temp-1); 

    if (right > temp) 
     q_sort(numbers, temp+1, right); 
} 

int main() 
{ 
    int x,y,i,j; 
    int *arr; 
    char **str; 
    int *count; 
    while(1) 
    { 
     scanf("%d%d",&x,&y); 
     if(x==0 && y==0)break; 
     str =(char **)malloc(sizeof(char *)*x); 
     count=(int*)malloc(sizeof(int)*x); 
     i=0; 
     while(i<x) 
     { 
      str[i]=(char *)malloc(sizeof(char)*y); 
      scanf("%s",str[i]); 
      i++; 
     } 
     //sizeof(str)/sizeof(*str) 
     q_sort(str,0,x-1);// sizeof(str)/sizeof(char *), sizeof(char *),cmp); 
     i=0; 
     j=0; 
     arr=(int *)malloc(sizeof(int)*x); 
     while(i<x) 
     { 
      arr[j]=1; 
      while(i<x-1 && strcmp(str[i],str[i+1])==0) 
      { 
       i++; 
       arr[j]+=1; 
      } 
      j++; 
      i++; 
     } 

     for(i=0;i<x;i++) 
     { 
      count[i]=0; 
     } 
     i=0; 
     while(i<j) 
     { 
      count[arr[i]-1]++; 
      i++; 
     } 
     for(i=0;i<x;i++) 
     { 
      printf("%d\n",count[i]); 
     } 
     free(count); 
     free(arr); 
     for(i=0;i<x;i++) 
      free(str[i]); 
     free(str); 

    } 
    return 0; 
} 
+3

你試過調試器嗎? –

+1

[SSCCE](http://sscce.org)意味着你提供了一些緊湊的東西。不要指望我們閱讀那些混亂,格式不正確的代碼。 – 2012-12-21 17:55:00

+0

使用'gcc -Wall -g'編譯所有警告和調試信息,並用'gdb'和'valgrind'進行調試; 'scanf'的''%d%d''格式看起來真的很可疑(或者至少檢查一下'scanf'的結果) –

回答

1

如果有一個數據文件:

20 20 
absinthe000001 
absinthe000002 
... 
absinthe000020 

Valgrind的警告(反覆):

==27941== Conditional jump or move depends on uninitialised value(s) 
==27941== at 0xCB9A: strcmp (mc_replace_strmem.c:721) 
==27941== by 0x100000AAB: q_sort (qs.c:16) 
==27941== 

我也得到線的裏姆斯含1或0

您已經下標失控。將下標打印添加到您的快速排序例程中,以查看發生了什麼問題。讀完數據後再添加打印,以確保您的數據符合您的想象。

你說:

它非常適用於小型輸入和所有的測試情況下,我能想到的

當我嘗試:

0 20 

作爲輸入,它行爲不端:

==28056== 
==28056== Invalid read of size 8 
==28056== at 0x100000A63: q_sort (qs.c:12) 
==28056== Address 0x100006160 is 0 bytes after a block of size 0 alloc'd 
==28056== at 0xB823: malloc (vg_replace_malloc.c:266) 
==28056== by 0x100000BB7: main (qs.c:57) 
==28056== 

當我嘗試:

1 20 
absinthe000001 

我得到1的打印流長。當我嘗試:

2 20 
absinthe000001 
absinthe000002 

我得到一個長長的交替0和1的流。坦率地說,我認爲你沒有嘗試過很多案例。排序代碼需要能夠正確處理0,1,2行。

問題的一部分當然是,你有一個while (1)循環,然後你不檢查你的scanf()調用。

while(1) 
{ 
    scanf("%d%d",&x,&y); 

錯誤的測試!

while (1) 
{ 
    if (scanf("%d%d", &x, &y) != 2) 
     break; 

請勿使用scanf();新手程序員要正確使用它實在太難了。我只用了四分之一個世紀的C語言編程;我不使用scanf(),除了回答使用它的SO問題。我使用fgets()來讀取行,並使用sscanf()來解析它們;更容易處理,並且你可以得到更好的錯誤報告(因爲你可以報告整個錯誤的行,而不僅僅是在scanf()已經損壞它之後剩下的)。

char buffer[4096]; 

while (fgets(buffer, sizeof(buffer), stdin) != 0) 
{ 
    if (sscanf(buffer, "%d%d", &x, &y) != 2) 
     break; 
    str = (char **)malloc(sizeof(char *)*x); 
    count = (int*)malloc(sizeof(int)*x); 
    for (i = 0; i < x; i++) 
    { 
     if (fgets(buffer, sizeof(buffer), stdin) != 0) 
      break; 
     str[i] = (char *)malloc(sizeof(char)*y); 
     if (sscanf(buffer, "%s", str[i]) != 1) 
      break; 
    } 

您應該檢查malloc()調用的結果;如果他們失敗了,你會得到一個分割違規或類似的東西。可以說,您應該創建一個格式字符串,以防止在您讀取數據到str[i]時發生溢出。

+0

如此真實。 'scanf'很容易被錯誤地使用。 –