2012-11-26 30 views
5

Ở đây tôi đang cố gắng để làm việc với các tính năng an toàn của C#: http://ideone.com/L9uwZ5trụy lạc với an toàn C#, cấp phát bộ nhớ ngăn xếp

tôi biết, mà theo cách như vậy trong C# là tồi tệ nhất, và tôi muốn thừa nhận, rằng có một số thông tin trong chủ đề. Nhìn vào từ "perversion".

Tôi muốn triển khai sắp xếp nhanh trong C# như kiểu C thuần túy (thậm chí không phải C++). Nó có thể điên rồ, nhưng chỉ muốn nhìn sâu vào khả năng của C# không an toàn.

Tôi luôn cố gắng sử dụng stackalloc nhà điều hành. Tôi biết, rằng đó là một phân bổ từ ngăn xếp, không phải từ đống, và đó là lý do tại sao tôi nhận được thất bại với việc thực hiện chương trình của tôi.

Nhưng tôi đã nhầm lẫn khi tôi không thấy bất kỳ ngoại lệ/lỗi nào trong chương trình này.

  • Tại sao tôi không nhận được bất kỳ ngoại lệ/lỗi rõ ràng nào?

Ngoài ra, như bạn nhìn thấy một phần nhận xét của mã:

struct Header 
{ 
    internal int* data; 
}; 

Header* object_header = stackalloc Header[sizeof(Header)]; 
object_header->data = stackalloc int[length]; 

tôi không thể biên dịch nó với dòng cuối cùng. Trình biên dịch C# cho biết, trong biểu thức này stackalloc không thể sử dụng được. Tại sao? dữ liệu là int * loại, vậy tại sao lỗi xảy ra ở đây?

Tôi chỉ muốn sử dụng khung ngăn xếp và không sử dụng đống. Tôi biết, rằng có một cách khác, nhưng đó là một phân bổ từ đống.

int*[] data = new int*[length * sizeof(int)]; 
IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(length * sizeof(int))); 
Marshal.WriteInt32(result, 0); 
for(int i = 0; i < length * sizeof(int); i++) d[i] = (int*)result; 

Ví dụ: nhưng không phân bổ theo chồng.

Làm cách nào để tôi có thể giải quyết tác vụ perversion của mình, rõ ràng với cú pháp phân bổ theo chồng và thuần túy trong ngôn ngữ C#.

C# đó không được tạo cho các mục tiêu như vậy và các tính năng như vậy là ngớ ngẩn - tôi biết, nhưng câu hỏi chính không phải là về ý nghĩa, đó là về các tính năng như vậy.

+0

Vui lòng đăng thông báo lỗi đầy đủ vì tôi hy vọng rằng nó sẽ cho chúng tôi biết * tại sao * nó không thể được sử dụng như thế. – usr

+0

@usr có vẻ như bạn chưa đọc tốt chủ đề của tôi :) vấn đề chính là: "Nhưng tôi đã nhầm lẫn khi tôi không thấy bất kỳ ngoại lệ/lỗi nào trong chương trình này". , Tôi không nhận được bất kỳ lỗi nào, chỉ hủy bỏ việc thực thi mà không có bất kỳ báo cáo lỗi nào. – Secret

+0

Bạn nói "Trình biên dịch C# cho biết, trong biểu thức này, stackalloc không thể được sử dụng." Đó không phải là vấn đề chính của bạn sao? – usr

Trả lời

5

Marc cho biết cách giải quyết khác, tôi sẽ cố gắng giải thích lý do tại sao điều này là bắt buộc. Bạn đang viết, có hiệu lực, không được quản lý mã nhưng phương pháp vẫn còn rất nhiều một phương pháp quản lý. Nó được biên dịch từ IL thành mã máy và khung ngăn xếp của nó và thanh ghi cpu sẽ được tìm kiếm bởi bộ thu gom rác để tham chiếu đối tượng.

Trình kích hoạt thực hiện hai các nhiệm vụ quan trọng khi biên dịch phương thức. Một là hiển nhiên và dễ thấy, dịch mã IL thành mã máy. Nhưng có một nhiệm vụ rất quan trọng khác và nó hoàn toàn vô hình, nó tạo ra siêu dữ liệu cho một phương thức. Bảng hiển thị phần nào của khung ngăn xếp chứa tham chiếu đối tượng và phần nào lưu trữ con trỏ và giá trị kiểu giá trị. Và tại điểm nào trong mã, thanh ghi cpu sẽ lưu trữ một tham chiếu đối tượng. Ngoài ra, tại điểm nào trong mã phương thức, một tham chiếu đối tượng nằm ngoài phạm vi. Lý do cho GC.KeepAlive(), một phương pháp khá độc đáo không tạo ra mã nào cả.

Bộ thu gom rác cần bảng đó để tìm các tham chiếu đối tượng một cách đáng tin cậy. Tuy nhiên, bảng này chỉ có một mức độ gián tiếp. Nó có thể mô tả không gian ngăn xếp được phân bổ cho object_header và đánh dấu con trỏ và vùng được trỏ tới là "không quét tìm tham chiếu đối tượng". Nó không thể mô tả các đoạn của không gian ngăn xếp khi bạn trực tiếp gán object_header-> dữ liệu. Nó không có thêm hướng dẫn để phân chia ngăn xếp thành các phần nhỏ hơn và mô tả Tiêu đề. Sử dụng biến cục bộ giả giải quyết vấn đề.

3

stackalloc muốn gán cho một biến.Các công trình sau đây nhưng bạn sẽ phải thực sự cẩn thận hủy gán rằng trước khi rời khỏi phương pháp này - nếu bạn để lại object_header->data điểm đến một vị trí trong ngăn xếp: điều xấu:

int* ptr = stackalloc int[length]; 
    object_header->data = ptr; 

Thực tế là nó phải được gán cho một biến địa phương là rõ ràng trong đặc tả:

địa phương biến-initializer:

...

stackalloc-initializer

stackalloc-initializer:

stackallockhông được quản lý kiểu[biểu]

+1

Bạn không deallocate một phân bổ stack. Nó sẽ tự động bị hủy khi thành viên hàm đó trả về. Xem: http://msdn.microsoft.com/en-us/library/aa664785(v=vs.71).aspx –

+2

@AdrianCiura bởi deallocate, tôi có nghĩa là đặt 'object_header-> data' thành cái gì khác; Tôi sẽ làm rõ –

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