2011-08-21 80 views
0

注意:我從來沒有遇到過這樣的規模問題,並且不知道如何佈置它,如果我把它弄錯了,請解釋我應該如何佈置它。如果你不能或不會幫助你的項目,我很高興簡單地瞭解這個問題。損壞的雙鏈表:0x0804d0c0(C++)?

我一直在寫一段代碼來練習面向對象的編程,但我遇到了一個我以前從未見過的錯誤(我一直在這個只有幾個月,並沒有得到很多時間學習,因爲我的時間被浪費在義務教育上)。內核本身(顯然)用我的代碼產生了這個錯誤。但是運行gdb(帶有調試符號)並沒有給我一個行號的想法。放入一個printf語句顯示它即使在條件不再滿足時也會循環一段時間循環?這對我來說看起來很奇怪,因爲它似乎沒有滿足條件,但它保持循環。它發生錯誤(我認爲)發生這種情況的原因是因爲「Stack」類中的某個地方爲整數數組重新分配負值大小的內存 - 但是,當我向Stack :: reloc添加if語句以便阻止它實現負數組大小,它仍然會消除錯誤。往下看它顯示了幾條其他信息,(引用gdb):

程序接收到的信號SIGABRT,中止。 0x0012d422在__kernel_vsyscall()

我沒有真正從SIGABRT的wiki頁面學到很多,我不認爲這個十六進制數字對我來說意味着什麼。這裏是我的代碼,分爲兩個階級,主要:

標題:

#include <cstdio> 
#include <cstdlib> 

Stack類:

class Stack { 
private: 
    int *stack; 
    int size; 
    void init(int *top) { 
     *top = 0; 
    } 

    void push2(int *s,int* top, int element) { 
     s[(*top)++] = element; 
    } 

    int pop2(int *s,int *top) { 
     return s[--(*top)]; 
    } 
    void reloc(int diff) { 
     if ((top+diff)>1) { 
      realloc(stack, (size+diff)); 
      size = size+diff; 
     } 
    } 

public: 
    int top; 
    Stack() { 
     init(&top); 
     size = 100; 
     stack = (int *)malloc(100 * sizeof(int)); 
    } 
    void push(int element) { 
     if (top>=(size-1)) reloc(100); 
     push2(stack, &top, element); 
    } 
    int pop() { 
     if ((top<(size-120)) && (top>100)) reloc(-100); 
     return (pop2(stack, &top)); 
    } 
    int sth() { 
     return size; 
    } 

};

類宇宙:

/*Universe is the casual layout for the universe*/ 
class Universe { 
    private: 
     int y_cog; //y axis center of gravity 
     int x_cog; //x axis " 
     int force; //weight of universe 
     int fps; //frames per second 
     int g; //acceleration under gravity 
     int G; //gravitational constant 

     //NB: velocity in d/s 
     //all stacks defined 
     Stack y_pos; //y axis position 
     Stack x_pos; //x axis " 
     Stack mass; //mass of object 
     Stack y_vel; //velocity on y axis 
     Stack x_vel; //velocity on x axis 
     Stack y_pos2; //stacks for repeating 
     Stack x_pos2; 
     Stack mass2; 
     Stack y_vel2; 
     Stack x_vel2; 

     //function 'increments' the center of gravity 
     void cog(int y, int x, int m) { 
      //ratio is offset of universe cog 
      //where 100 is exectly half way 
      int ratio = ((m*100)/(force))/2; 
      //set the center of gravity the ratio beween the objects 
      y_cog = y_cog-(((y_cog-y)/100)*ratio); 
      x_cog = x_cog-(((x_cog-x)/100)*ratio); 
      force = m+force; 
     } 

     /*moves the object at the top of the stack and alters velocity 
     according to previouse velocity and force towards the universe 
     center of gravity*/ 
     void move() { 
      int yp, xp, m, yv, xv, vi, yvi, xvi, rm; 
      yp = y_pos2.pop(); 
      xp = x_pos2.pop(); 
      m = mass2.pop(); 
      yv = y_vel2.pop(); 
      xv = x_vel2.pop(); 
      //important part 
      //set the position according to velocity and frame rate 
      yp = yp+(yv/fps); 
      xp = xp+(xv/fps); 
      //find the ratio share of velocity 
      vi = ((g*100)/fps); //velocity increase 
      rm = ((y_cog-yp)+(x_cog-xp)); //ratio maximum 
      if (rm==0) rm = 1; 
      yvi = ((vi/rm)*(y_cog-yp))/100; 
      xvi = ((vi/rm)*(x_cog-xp))/100; 
      yv = yvi; 
      xv = xvi; 
      //push everything back 
      y_pos.push(yp); 
      x_pos.push(xp); 
      mass.push(m); 
      y_vel.push(yv); 
      x_vel.push(xv); 
     } 

    public: 
     Universe() { 
      y_cog = 0; 
      x_cog = 0; 
      force = 0; 
      fps = 10; 
      g = 10; 
      //all stacks initialised 
      y_pos = Stack(); 
      x_pos = Stack(); 
      mass = Stack(); 
      y_vel = Stack(); 
      x_vel = Stack(); 
     } 

     void add(int yp, int xp, int m, int yv, int xv) { //adds object to stack 
      y_pos.push(yp); 
      x_pos.push(xp); 
      mass.push(m); 
      y_vel.push(yv); 
      x_vel.push(xv); 
     } 

     void run() { 
      int yp, xp, m, yv, xv; 
      while (y_pos.top<=0) { //reposition center of gravity 
       //mainly pushing things around 
       yp = y_pos.pop(); 
       xp = x_pos.pop(); 
       m = mass.pop(); 
       yv = y_vel.pop(); 
       xv = x_vel.pop(); 
       cog(yp, xp, m); //the important part 
       y_pos2.push(yp); 
       x_pos2.push(xp); 
       mass2.push(m); 
       y_vel2.push(yv); 
       x_vel2.push(xv); 
      } 
      while (y_pos2.top<1) { 
       move(); 
      } 
     } 

     void outh() { //human output 
      int yp, xp, m, yv, xv; 
      while (y_pos.top<=0) { 
       yp = y_pos.pop(); 
       xp = x_pos.pop(); 
       m = mass.pop(); 
       yv = y_vel.pop(); 
       xv = x_vel.pop(); 
       y_pos2.push(yp); 
       x_pos2.push(xp); 
       mass2.push(m); 
       y_vel2.push(yv); 
       x_vel2.push(xv); 
       printf("%d, %d\t%d\t%d\n", yp, xp, m, yv+xv); 
      } 
      while (y_pos2.top<=0) { 
       y_pos.push(y_pos2.pop()); 
       x_pos.push(x_pos2.pop()); 
       mass.push(mass.pop()); 
       y_vel.push(y_vel.pop()); 
       x_vel.push(x_vel.pop()); 
      } 
     }  
}; 

主函數:

int main() { 
    Universe main = Universe(); 
    main.add(10, 10, 10, 0, 0); 
    main.add(5, 5, 5, 0, 0); 
    int i; 
    for (i = 1; i<100; i++) { 
     main.run(); 
     main.outh(); 
     printf("\n"); 
    } 
    return 0; 
} 

GDB運行結果(調試符號):

Starting program: /home/james/Desktop/coding/Universe/debug 
*** glibc detected *** /home/james/Desktop/coding/Universe/debug: corrupted double-linked list: 0x0804d0c0 *** 
======= Backtrace: ========= 
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x2d4591] 
/lib/tls/i686/cmov/libc.so.6(+0x70ce3)[0x2d9ce3] 
/lib/tls/i686/cmov/libc.so.6(realloc+0xdd)[0x2d9f9d] 
/home/james/Desktop/coding/Universe/debug[0x80486b2] 
/home/james/Desktop/coding/Universe/debug[0x804872c] 
/home/james/Desktop/coding/Universe/debug[0x80489b0] 
/home/james/Desktop/coding/Universe/debug[0x8048cec] 
/home/james/Desktop/coding/Universe/debug[0x80485fd] 
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x27fbd6] 
/home/james/Desktop/coding/Universe/debug[0x80484d1] 
======= Memory map: ======== 
00110000-0012b000 r-xp 00000000 08:01 393241  /lib/ld-2.11.1.so 
0012b000-0012c000 r--p 0001a000 08:01 393241  /lib/ld-2.11.1.so 
0012c000-0012d000 rw-p 0001b000 08:01 393241  /lib/ld-2.11.1.so 
0012d000-0012e000 r-xp 00000000 00:00 0   [vdso] 
0012e000-00217000 r-xp 00000000 08:01 2625203 /usr/lib/libstdc++.so.6.0.13 
00217000-00218000 ---p 000e9000 08:01 2625203 /usr/lib/libstdc++.so.6.0.13 
00218000-0021c000 r--p 000e9000 08:01 2625203 /usr/lib/libstdc++.so.6.0.13 
0021c000-0021d000 rw-p 000ed000 08:01 2625203 /usr/lib/libstdc++.so.6.0.13 
0021d000-00224000 rw-p 00000000 00:00 0 
00224000-00248000 r-xp 00000000 08:01 525255  /lib/tls/i686/cmov/libm-2.11.1.so 
00248000-00249000 r--p 00023000 08:01 525255  /lib/tls/i686/cmov/libm-2.11.1.so 
00249000-0024a000 rw-p 00024000 08:01 525255  /lib/tls/i686/cmov/libm-2.11.1.so 
0024a000-00267000 r-xp 00000000 08:01 393299  /lib/libgcc_s.so.1 
00267000-00268000 r--p 0001c000 08:01 393299  /lib/libgcc_s.so.1 
00268000-00269000 rw-p 0001d000 08:01 393299  /lib/libgcc_s.so.1 
00269000-003bc000 r-xp 00000000 08:01 525247  /lib/tls/i686/cmov/libc-2.11.1.so 
003bc000-003bd000 ---p 00153000 08:01 525247  /lib/tls/i686/cmov/libc-2.11.1.so 
003bd000-003bf000 r--p 00153000 08:01 525247  /lib/tls/i686/cmov/libc-2.11.1.so 
003bf000-003c0000 rw-p 00155000 08:01 525247  /lib/tls/i686/cmov/libc-2.11.1.so 
003c0000-003c3000 rw-p 00000000 00:00 0 
08048000-0804a000 r-xp 00000000 08:5  /home/james/Desktop/coding/Universe/debug 
0804a000-0804b000 r--p 00001000 08:5  /home/james/Desktop/coding/Universe/debug 
0804b000-0804c000 rw-p 00002000 08:5  /home/james/Desktop/coding/Universe/debug 
0804c000-0806d000 rw-p 00000000 00:00 0   [heap] 
b7e00000-b7e21000 rw-p 00000000 00:00 0 
b7e21000-b7f00000 ---p 00000000 00:00 0 
b7fed000-b7fef000 rw-p 00000000 00:00 0 
b7ffe000-b8000000 rw-p 00000000 00:00 0 
bffeb000-c0000000 rw-p 00000000 00:00 0   [stack] 

Program received signal SIGABRT, Aborted. 
0x0012d422 in __kernel_vsyscall() 
+2

在這麼多的代碼中很難發現錯誤。無論是爲了你自己,還是爲了我們自己,你都應該嘗試刪除儘可能多的代碼而不刪除錯誤。例如,'Universe :: move()'中的計算可能與錯誤無關。嘗試取出可能不相關的代碼,編譯,運行並重復,只要您仍然可以看到錯誤。最後留下的內容應該可以揭示原因:) –

+2

問題標題似乎有誤導性。我在代碼中看不到雙鏈表。 –

+1

@從GDB退出它的一個錯誤可能是內存錯誤。 還可以使用調試符號編譯用戶嗎?它看起來像你不是那麼gdb只是給地址,而不是符號名稱 –

回答

5

的一個大問題,realloc()的行應該成爲:

stack = realloc(stack, (size+diff)); 
+3

'stack = realloc(stack,(size + diff)* sizeof(int));' –

+0

謝謝,我應該說明一下(看看我如何在Stack :: Stack中使用malloc)我還需要指定它需要和整數數組:stack =(int *)realloc(stack,(size + diff)* sizeof(int)); – user825962

+0

我沒有足夠的代表表示抱歉,但謝謝 – user825962

1

由於內存損壞,您的程序運行異常並崩潰。

在你的情況下,這可能是由寫入無效指針造成的。由於您的代碼中直接使用指針的唯一部分是您的Stack類,因此很可能是Stack有錯誤,或者Universe有一個錯誤導致Stack被錯誤地使用。

1

標準庫已經提供了堆棧實現,所以我不明白你爲什麼要實現自己的。你的問題是你沒有提供析構函數,複製構造函數或複製賦值操作符。當析構函數被調用時,它將釋放指針,但不釋放它指向的對象。這將導致內存泄漏。同樣,當複製構造函數或賦值運算符被調用時,它將複製指針,而不是它指向的對象。如果你已經正確地定義了析構函數,而不是複製函數,如果對象被複制(不正確),你可能會刪除不存在的對象。

另一個問題是您錯誤地使用了realloc。它應該是:

stack = realloc(stack, (size + diff) * sizeof(int)); 

這是萬一分配的位置發生變化。編輯:另一件我注意到,由於來自另一個答案的評論,是你必須乘以sizeof(int)大小,因爲它期望的大小以字節爲單位。

上述問題並不是你的程序無限循環的原因,但值得一提的是。真正的問題是循環。您期待循環執行,而top小於或等於0(或在一種情況下小於1)。真的,應該是top多於 0,因爲0表示堆棧中沒有更多的元素。由於您允許堆棧訪問索引小於0的元素,因此會出現錯誤。無論如何,它看起來像循環只能滿足他們的條件,所以你可以刪除它們。

0

您的程序中的某處您試圖使用無效指針。內存損壞很難找到,特別是對於初學者。引用Brian Kernighan的話:「當你盡力編寫你的代碼時,你將如何調試它?」 GDB可以幫助您處理複雜的程序,但在這種情況下,我會轉向另一個方向。

幸運的是Stack似乎是您的程序處理內存的唯一地點。 我的建議是把一些斷言到它的方法是這樣的:

// at the beginning of pop(): 
    assert(top > 1); 

這將幫助你找到你的代碼的其他部分,這是濫用你的Stack類錯誤:

while (y_pos.top<=0) { 
    yp = y_pos.pop(); 

這會導致堆棧下溢,即使Stack是正確的。正如其他答案指出的,realloc沒有設置指針。

還有一些其他的點,我會反對你的代碼:

  • 使用標準庫的容器,如std::stack<T>std::vector<T>。除非必須,否則不要亂指針。
  • 請勿使用mallocfree,如果必須,請使用newdelete
  • 嘗試在數據結構中放置像x,y,質量,速度等數據以減少重複性代碼。