难以理解的分段错误:11

时间:2016-03-14 22:26:33

标签: c arrays segmentation-fault

我有以下代码来实现最大子序列长度搜索。我无法检查程序是否正确,因为运行我的程序会产生分段错误。

程序编译得很好。

请告诉我这里我做错了什么:

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

int main()
{
   int a[6]={1,-2,4,33,0,-6};      //THE ACTUAL SEQUENCE
   int count_a[6]={1,1,1,1,1,1};   //ARRAY TO KEEP COUNT OF MAXIMUM LENGTHS FROM POINT OF VIEW OF EACH ELEMENT OF ARRAY A
   int i=0;
   int j=0;
   int k=0;
   for(k=1;k<6;k++)
   {
      j=k;
      printf("k's value:%d\t",j);   //JUST FOR TESTING
      while(1)
      {
         if(a[i]<a[j])
         {
             if(count_a[j]<(1+count_a[i]))
             {
                count_a[j]=1+count_a[i];
             }
         }
         if(j-1==1)
         {
             break;
         }
         else
         {
             i++;
         }
     }
     i=0;
   }


   /* THIS IS FOR ME TO CHECK WHETHER THE LENGTH VALUES HAVE BEEN UPDATED IN THE COUNT_A ARRAY*/
   for(k=0;k<6;k++)
   {
       printf("%d\t",count_a[k]);
   }
   return 0;
}

2 个答案:

答案 0 :(得分:2)

你有无限循环。 j=k;然后while(1)只能在if(j-1==1)时终止。在第一次迭代k设置为1,因此j也设置为1。永远不要因为1-1!=1而休息。您的j永远不会在while(1)循环中更改。

i++始终是选项。当i变大时,它会尝试从数组count_a[i]外部读取,从而导致段错误。

答案 1 :(得分:2)

让我们使用clang's address sanitizer来弄清楚发生了什么:

[3:41pm][wlynch@watermelon /tmp] clang -g -fsanitize=address blah.c
[3:41pm][wlynch@watermelon /tmp] ./a.out
=================================================================
==22763==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff52950958 at pc 0x00010d2b0953 bp 0x7fff52950910 sp 0x7fff52950908
READ of size 4 at 0x7fff52950958 thread T0
    #0 0x10d2b0952 in main blah.c:20
    #1 0x7fff851205ac in start (/usr/lib/system/libdyld.dylib+0x35ac)
    #2 0x0  (<unknown module>)

Address 0x7fff52950958 is located in stack of thread T0 at offset 56 in frame
    #0 0x10d2b072f in main blah.c:8

  This frame has 2 object(s):
    [32, 56) 'a' <== Memory access at offset 56 overflows this variable
    [96, 120) 'count_a'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow blah.c:20 main
Shadow bytes around the buggy address:
  0x1fffea52a0d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffea52a0e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffea52a0f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffea52a100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffea52a110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1fffea52a120: 00 00 00 00 f1 f1 f1 f1 00 00 00[f2]f2 f2 f2 f2
  0x1fffea52a130: 00 00 00 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
  0x1fffea52a140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffea52a150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffea52a160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffea52a170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==22763==ABORTING
k's value:1 Abort

因此,您可以在a[]结束后访问。

如果我减少你的代码,我们可以看到这显然是可能的:

k = 1;
j = k;

while(1)
{
    if(a[i]<a[j])
        if(count_a[j]<(1+count_a[i]))
            count_a[j]=1+count_a[i];
    if(j-1==1)
        break;
    else
        i++;
}

请注意,j-1在此次迭代中从不等于1(它始终为0),因此您将增加i直到它已经过了a