01/10/2018, 08:24

Vì sao khi gán 1 struct (có thành phần là con trỏ) này sang 1 struct khác lại bị lỗi mặc dù kết quả ra đúng?

E có 1 đoạn code đơn giản sau để gán 1 struct A sang 1 struct B (có thành phần là con trỏ)

#include <iostream>
typedef struct {
    int x;
    float *y;
} Struct;
int main()
{
    Struct *var = new Struct;
    var->x = 1;
    var->y = new float;
    *(var->y) = 1.1;
    std::cout << var->x << "	" << *(var->y) << std::endl;
    Struct *var2 = new Struct;
    var2->y = new float;
    var2 = var;
    std::cout << var2->x << "	" << *(var2->y) << std::endl;
    delete var2;
    delete var;
    return 0;
}

Nhìn chung thì khi compile & run trên Codeblocks thì chương trình vẫn cho ra kết quả đúng nhưng lại bị lỗi runtime, các pro có biết tại sao ko, giúp em với

*grab popcorn* viết 10:25 ngày 01/10/2018

delete var2;
delete var;

2 dòng này giang hồ nói rằng sẽ gây nên undefined behavior. Vì nó giải phóng cùng 1 vùng nhớ nhưng tới 2 lần.
Nên hành vi của nó là ko đoán được, có thể crash như bạn, có thể ko lỗi gì, có thể lỗi nhưng ko gây crash,… (Search delete a pointer twice sẽ có câu trả lời)

Tuy nhiên nếu giải phóng con trỏ null thì ko có gì xảy ra, thế nên ngta hay khuyên trỏ con trỏ về null sau khi giải phóng là vậy.
http://en.cppreference.com/w/cpp/memory/new/operator_delete

In all cases, if ptr is a null pointer, the standard library deallocation functions do nothing.

Long Dragon viết 10:40 ngày 01/10/2018

Tuy nhiên nếu giải phóng con trỏ null thì ko có gì xảy ra, thế nên ngta hay khuyên trỏ con trỏ về null sau khi giải phóng là vậy.

Có nghĩa là khi có nhiều hơn 2 con trỏ nằm chung 1 vùng nhớ thì ta chỉ việc trỏ 1 trong chúng về null rồi muốn delete bao nhiều lần cũng được hả a ?

var2->y = new float;

E thử xóa cái dòng này thì chương trình vẫn chạy đúng a nhỉ ?

rogp10 viết 10:31 ngày 01/10/2018

E thử xóa cái dòng này thì chương trình vẫn chạy đúng a nhỉ ?

Ậy, cái này cũng undefined luôn, thao tác như vậy có thể bị văng lỗi.

Long Dragon viết 10:30 ngày 01/10/2018

Ậy, cái này cũng undefined luôn, ghi như vậy có thể bị văng lỗi.

vậy có nghĩa là nó thuộc trường hợp lỗi nhưng ko crash hả a ?

*grab popcorn* viết 10:29 ngày 01/10/2018

Có nghĩa là khi có nhiều hơn 2 con trỏ nằm chung 1 vùng nhớ thì ta chỉ việc trỏ 1 trong chúng về null rồi muốn delete bao nhiều lần cũng được hả a ?

Không phải, 1 địa chỉ đã được giải phóng rồi thì ko được giải phóng lại (trừ khi nó được cấp phát lại). Như var đang trỏ tới 123, var2 cũng trỏ tới 123. bạn giải phóng var = giải phóng vùng nhớ bắt đầu từ địa chỉ 123. -> nếu bạn giải phóng tiếp var2 là giải phóng địa chỉ 123 1 lần nữa -> undefined behavior.

Còn giải phóng rồi xài tiếp được ko thì rogp10 đã có nói, và đây thêm 1 lý do để ta luôn trỏ con trỏ về null khi giải phóng.

Long Dragon viết 10:25 ngày 01/10/2018

@drgnz @rogp10 mà e có nghe 1 anh nói là ko thể gán 2 struct có thành phần là con trỏ cho nhau, vậy có đúng ko nhỉ ? (nếu đúng thì vì sao đoạn code trên lại run ok ?
)

rogp10 viết 10:37 ngày 01/10/2018

Nếu gán bt thì 2 cái struct có 2 pointer trỏ về cùng một resource => delete đi là sẽ sinh lỗi.

Bài liên quan
0