2013-08-05 26 views
5

Tiếp theo tình hình, tôi có một struct chứa con trỏ đến số nguyên biến như thế này:Có hợp pháp để tham khảo bộ nhớ chưa được khởi tạo mà không cần truy cập vào nó?

struct Structure[] = { 
    { &Var[0], &Var[1] }, 
    { &Var[2], &Var[3] } 
}; 

Thing là: Var được uninitialized lần đầu tiên struct này được lấp đầy. (Như trong: NULL) Ngay sau (trên thẻ đầu tiên) biến Var sẽ được khởi tạo và các tham chiếu sẽ được cập nhật tương ứng.

Tôi thấy không có lý do nào cho sự cố này, nhưng tôi muốn chuyên môn của bạn trên đó. Có hợp pháp khi đặt tham chiếu đến bộ nhớ không hợp lệ (với chỉ số mảng) vào một mảng như thế này không? Hay tôi cần một cách tiếp cận khác cho tình huống này?

Tôi không truy cập nội dung của các biến này cho đến sau lần khởi tạo đầu tiên.

Cảm ơn bạn rất nhiều.

Chỉnh sửa: Vì lợi ích của người đọc trong tương lai: Var là biến con trỏ chung, được khởi tạo thành NULL lúc đầu. Việc khởi tạo biến nó thành một mảng bằng cách sử dụng new.

+1

Tôi chắc chắn rằng câu trả lời là không và một số người tối ưu hóa sẽ phá vỡ mã của bạn. – SLaks

+1

"Hay tôi cần một cách tiếp cận khác cho tình huống này?" Hmm, có thể, khởi tạo biến? –

+0

@DanielDaranas Tôi là. Tuy nhiên chỉ sau SAU mảng đã được lấp đầy. Đó là một hàm được gọi nhiều lần. – ATaylor

Trả lời

7

Tôi giả định rằng Var là đối tượng con trỏ và giá trị hiện tại của nó là một con trỏ rỗng. Điều này được ngụ ý bởi tuyên bố của bạn:

Var chưa được khởi tạo lần đầu tiên cấu trúc này được điền. (Như trong: NULL)

Tôi cũng giả định rằng Var không được xác định tại phạm vi khối. Nếu nó được định nghĩa ở phạm vi khối, và bạn chưa khởi tạo hoặc gán giá trị cho nó, thì giá trị của nó là rác, không nhất thiết là giá trị con trỏ null và bất kỳ nỗ lực nào để tham chiếu đến giá trị của nó có hành vi không xác định.

Hành vi không xác định.

Nếu Var == NULL, thì &Var[N] có hành vi không xác định.

arr[index] theo định nghĩa tương đương *(arr + index), vì vậy &Var[N] tương đương với &(*(Var + N)). Hành vi của số học con trỏ được xác định theo các yếu tố của đối tượng mảng mà con trỏ trỏ tới (với một đối tượng được coi là mảng một phần tử) và một con trỏ null không trỏ tới bất kỳ thứ gì.

Một digression:

C một cách rõ ràng nói rằng &*x được đánh giá là x, và &[x[i]) được đánh giá là x+i; C++ không nói điều này, do đó toán hạng của & phải hợp lệ. C++ có một trường hợp đặc biệt để thêm 0, được xác định tốt ngay cả đối với con trỏ rỗng (C không có trường hợp đặc biệt nào). Nhưng &Var[0] vẫn không hợp lệ trong cả C và C++, nhưng vì các lý do khác nhau. Trong C, nó tương đương với Var + 0, nhưng thêm 0 vào một con trỏ rỗng có hành vi không xác định. Trong C++, đó là không phải tương đương với Var + 0; thay vì nó tương đương với &(*(Var + 0)); Var + 0 là một con trỏ rỗng và dereferencing nó có hành vi không xác định.)

Kết thúc quá trình phân tích.

Có, chỉ cần tính toán địa chỉ không hợp lệ có hành vi không xác định, ngay cả khi nó không bao giờ bị hủy đăng ký.

Đây là văn bản có liên quan từ tiêu chuẩn ISO C++ 2011, 5.7 [expr.add] đoạn 5; lưu ý đặc biệt là cuối cùng:

Khi biểu thức có loại tích phân được thêm hoặc trừ từ con trỏ, kết quả có loại toán hạng con trỏ. Nếu điểm toán tử con trỏ tới phần tử của đối tượng mảng và mảng đủ lớn, kết quả sẽ trỏ đến phần tử được bù đắp từ phần tử gốc sao cho sự khác biệt của các phần tử của biểu thức tích phân. Nói cách khác, nếu biểu thức P trỏ đến phần tử thứ i của đối tượng mảng , biểu thức (P) + N (tương đương, N + (P)) và (P) -N (trong đó N có giá trị n) trỏ đến, tương ứng, i + n-th và i - các phần tử thứ n của đối tượng mảng, miễn là chúng tồn tại. Hơn nữa, nếu biểu thức P trỏ đến phần tử cuối cùng của đối tượng mảng, biểu thức (P) +1 điểm một phần tử cuối cùng của đối tượng mảng, và nếu biểu thức Q trỏ một phần tử cuối cùng của mảng đối tượng, biểu thức (Q) -1 điểm cho phần tử cuối cùng của đối tượng mảng . Nếu cả toán hạng con trỏ và điểm kết quả đến các phần tử của cùng một đối tượng mảng hoặc một phần tử cuối cùng của đối tượng mảng thì việc đánh giá sẽ không tạo ra tràn; nếu không, hành vi không xác định.

+0

Bạn có thể cung cấp tham chiếu khi thực hiện phép tính trên con trỏ null không? Hay tôi hiểu lầm những gì bạn đang nói? –

+0

Nhưng nếu 'Var' là một mảng, và không phải là một con trỏ, thì không có vấn đề gì. –

+1

@MarkB Nó có liên quan đến định nghĩa pháp lý của 'NULL'. Nếu 'NULL' được định nghĩa là' ((void *) 0) '(hợp pháp trong C, bất hợp pháp trong C++), thì làm bất kỳ số học nào trên đó là bất hợp pháp. (Và rõ ràng, nếu 'NULL' được định nghĩa là chỉ' 0', thì 'NULL + 0' là hợp pháp.) –

2

Vì bạn không sử dụng các giá trị cho đến sau lần vượt qua đầu tiên, hãy làm điều đúng và khởi tạo con trỏ của cấu trúc của bạn để thay thế. Sau đó, đặt các giá trị phù hợp khi bạn biết chúng. Nếu bạn sử dụng cách tiếp cận đó, vấn đề "là nó hợp pháp" của bạn sẽ biến mất!

+0

+1. Trên thực tế, 'struct Structure [2];' là khá đủ. Nếu kết quả khởi tạo không bao giờ được sử dụng, thì không cần thiết trong quá trình khởi tạo này. –

0

Để trả lời câu hỏi cụ thể (quên mã mẫu): có, bạn có thể tham chiếu đến bộ nhớ chưa được khởi tạo, bạn không thể dereference và mong đợi hành vi được xác định.

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