2017-12-20 145 views
25

Tôi có vấn đề sau:Dữ liệu con trỏ mảng được xóa ở giữa các cuộc gọi chức năng mà không có lệnh rõ ràng?

Trong chương trình C++ tôi có cấu trúc dữ liệu chung được khai báo là Renderer Rendering_Handler, có chứa trường thành viên được xác định là vector<Render_Info> visble objects.

Bản thân cấu trúc dữ liệu đang làm gì không quan trọng, chúng là trình bao bọc cần thiết để dữ liệu trừu tượng song song với chương trình của tôi.

Để rõ ràng, Rendering_Handler hoàn toàn toàn cầu và thực tế là một singleton (tôi có thể xác nhận 100% rằng hàm tạo đã được gọi một lần và chỉ một lần cho lớp này).

Tôi đã tuyên bố phương pháp lớp sau đây:

Render_Info* Renderer::add_Render_Info() 
{ 
    visible_objects.push_back(Render_Info()); 
    return &(visible_objects.back()); 
} 

đủ đơn giản, nó tạo ra một Render_Info cấu trúc mới, gắn nó vào mảng visible_objects và trả về một con trỏ đến đối tượng.

Một cấu trúc dữ liệu khác nhau được gọi là Chunk có một constructor định nghĩa là

Chunk::Chunk(vec3 offset, World* w) 
{ 
    /*initialize some values*/ 

    draw_info = Rendering_Handler->add_Render_Info(); 
    draw_info->VBOs = vector<GLuint>(5); 

    /*initialize OpenGL VAOs, VBOs and other buffer objects*/ 

    cout << draw_info->VBOs.size() << endl; 
    cout << draw_info << endl; 
} 

Nó cũng có một phương pháp định nghĩa là:

void Chunk::update_render_info() 
{ 
    cout << draw_info->VBOs.size() << endl; 
    cout << draw_info << endl; 

    /*OpenGL stuff*/ 

} 

Và cuối cùng

Chúng tôi có phương pháp mà khởi tất cả mọi thứ :

World::World() 
{ 
    /*Initialize chunks in a circular 3D array*/ 
    loaded_chunks = new Chunk_Holder(h_radius, h_radius, v_radius, this); 

    for(int i=0; i<h_radius; i++) 
    { 
     for(int j=0; j<h_radius; j++) 
     { 
      for(int k=0; k<v_radius; k++) 
      { 
       (*loaded_chunks)(i,j,k)->update(); 
      } 
     } 
    } 
} 

Đầu ra của rpgram là:

enter image description here

...

enter image description here

Hãy tập trung vào các But 2 và cuối cùng 2 dòng đầu ra, tương ứng với các in câu lệnh tôi đã thêm để gỡ lỗi.

2 dòng đầu tiên chỉ ra rằng 5 yếu tố đã được thêm vào bộ đệm tại địa điểm 0x556edb7ae200

2 dòng cuối cùng nói với tôi rằng cùng một bộ đệm (giống từ vị trí bộ nhớ là như nhau) bây giờ chứa 0 tố.

Như bạn có thể thấy từ các snaps của mã, không có chức năng được gọi là giữa việc tạo các khối và cập nhật chúng. Có ai có ý tưởng về những gì có thể gây ra sự bất hòa của những yếu tố này không?

Tôi đã không đặt đúng bộ nhớ? Các đối tượng này có bị xóa mà không có kiến ​​thức của tôi do phân bổ sai không?

+16

'visible_objects.push_back()' cuộc gọi có thể làm mất hiệu lực tất cả các con trỏ đến các phần tử 'visible_objects', để lại tất cả' draw_info'pointers của bạn đang lơ lửng. –

+0

Chụp OHHHH, ý bạn là, nó sẽ phân bổ lại bộ nhớ nếu nó vượt quá giới hạn được phân bổ trước đó, do đó di chuyển từng con trỏ đến một vị trí mới? – Makogan

+0

Cho bit mã không tạo ra bất kỳ đầu ra nào cả và bạn không bao giờ đặt trước bất kỳ bộ nhớ nào (điều này cũng sẽ giúp ngăn ngừa mất hiệu lực con trỏ). – VTT

Trả lời

9

Tôi nghĩ rằng vấn đề là bạn đang lưu trữ con trỏ tới các phần tử trong vectơ và đồng thời bạn gọi số vector::push_back mà giờ đây phải thay đổi kích cỡ vectơ và di chuyển tất cả các phần tử sang bộ nhớ mới. Điều này sẽ làm mất hiệu lực tất cả các con trỏ bạn đã có được trước đây.

Để cung cấp cho bạn thêm ngữ cảnh: vector lưu trữ các phần tử của nó trong một đoạn bộ nhớ liên tục. Khi vector::push_back được gọi và không còn dung lượng trống trong bộ nhớ này thì vector sẽ cấp phát một đoạn bộ nhớ khác với kích thước gấp đôi kích thước của đoạn cũ. Sau đó, nó sẽ sao chép/di chuyển tất cả các phần tử từ đoạn cũ sang đoạn mới. Cuối cùng đoạn cũ sẽ bị phá hủy. Khi bạn gọi &(visible_objects.back()), bạn sẽ nhận được một địa chỉ trong bộ nhớ nằm bên trong bộ nhớ hiện tại thuộc sở hữu của visible_objects. Nếu sau đó visible_objects.push_back được gọi và visible_objects phải di chuyển sang bộ nhớ lớn hơn mới thì tất cả các địa chỉ thu được trước sẽ bị cũ khi chúng trỏ đến đoạn bộ nhớ cũ đã bị hủy.

Các vấn đề liên quan