Bộ nhớ phân bổ


11

Bạn đang thiết kế một ngôn ngữ lập trình bí truyền mới và một tính năng bạn quyết định thêm là phân bổ bộ nhớ động. Ngôn ngữ của bạn chỉ định một không gian địa chỉ ảo dành riêng cho không gian chương trình của người dùng. Điều này tách biệt với không gian địa chỉ được sử dụng bởi bộ cấp phát bộ nhớ cho bất kỳ trạng thái bên trong nào.

Để giúp giảm chi phí phân phối việc triển khai của bạn, kích thước của mã phải càng nhỏ càng tốt.

Giao diện

Bạn phải cung cấp ba chức năng: khởi tạo, phân bổ và phân bổ.

Khởi tạo

Hàm này có một tham số nguyên dương duy nhất N. Điều này có nghĩa là chương trình của người dùng có Nbyte trong không gian địa chỉ mà từ đó có N-1byte để phân bổ bộ nhớ. Địa chỉ 0được dành riêng cho "null".

Nó được đảm bảo rằng chức năng này sẽ được gọi chính xác một lần trước khi có bất kỳ cuộc gọi phân bổ / thỏa thuận nào.

Lưu ý rằng chức năng này không cần phân bổ bất kỳ bộ nhớ vật lý nào cho không gian địa chỉ ảo của chương trình người dùng; về cơ bản bạn đang tạo ra "giao diện" của bộ cấp phát bộ nhớ rỗng.

Chỉ định

Hàm cấp phát phải lấy một yêu cầu về số byte bộ nhớ để phân bổ. Đầu vào được đảm bảo là tích cực.

Hàm của bạn phải trả về một địa chỉ số nguyên cho đầu khối được phân bổ hoặc 0để biểu thị rằng không có khối liền kề nào có kích thước được yêu cầu. Nếu một khối liền kề của kích thước có sẵn có sẵn ở bất cứ đâu trong không gian địa chỉ bạn phải phân bổ!

Bạn phải đảm bảo rằng không có hai khối được phân bổ trùng nhau.

Giao dịch viên

Hàm deallocate phải lấy một địa chỉ bắt đầu của một khối được phân bổ và tùy ý cũng có thể lấy kích thước của khối đã cho.

Bộ nhớ đã được xử lý lại có sẵn để phân bổ. Giả định rằng địa chỉ đầu vào là một địa chỉ hợp lệ.

Ví dụ triển khai Python

Lưu ý rằng bạn có thể chọn bất kỳ phương pháp nào để theo dõi trạng thái nội bộ; trong ví dụ này, cá thể lớp theo dõi nó.

class myallocator:
    def __init__(self, N):
        # address 0 is special, it's always reserved for null
        # address N is technically outside the address space, so use that as a
        # marker
        self.addrs = [0, N]
        self.sizes = [1, 0]

    def allocate(self, size):
        for i,a1,s1,a2 in zip(range(len(self.addrs)),
                                 self.addrs[:-1], self.sizes[:-1],
                                 self.addrs[1:]):
            if(a2 - (a1+s1) >= size):
                # enough available space, take it
                self.addrs.insert(i+1, a1+s1)
                self.sizes.insert(i+1, size)
                return a1+s1
        # no contiguous spaces large enough to take our block
        return 0

    def deallocate(self, addr, size=0):
        # your implementation has the option of taking in a size parameter
        # in this implementation it's not used
        i = self.addrs.index(addr)
        del self.addrs[i]
        del self.sizes[i]

Chấm điểm

Đây là mã golf; mã ngắn nhất trong byte thắng. Bạn không cần lo lắng về việc hết bộ nhớ cho bất kỳ trạng thái nội bộ nào theo yêu cầu của người cấp phát.

Lỗ vòng tiêu chuẩn áp dụng.

Bảng xếp hạng


3
Tôi nghi ngờ danh sách Python chiếm chính xác một byte cho mỗi phần tử. "Bộ nhớ được phân bổ" phải ở dạng byte hay chỉ có thể là "kiểu danh sách / mảng chung của ngôn ngữ của bạn"?
Doorknob

4
Không yêu cầu phân bổ thực tế (ngoại trừ bất cứ điều gì bạn muốn cho theo dõi trạng thái nội bộ, trên không gian địa chỉ ảo của chính nó); bạn chỉ trả lại số nguyên cho một số không gian địa chỉ ảo hữu hạn trừu tượng.
hellowworld922

To help reduce the cost of distributing your implementation the size of the code must be as small as possiblehoặc nó có thể hiệu quả (nhỏ và hiệu quả không giống nhau) càng tốt? : D
Bộ giải mã


Mặc dù thử thách này được thúc đẩy với nền tảng thiết kế ngôn ngữ, thiết kế ngôn ngữ không thực sự là một phần của nhiệm vụ (thay vì thực hiện các phần của một), vì vậy tôi đã xóa thẻ.
Martin Ender

Câu trả lời:


4

Hồng ngọc, 80

i,a,d=->n{$m=?o*n},->n{$m.sub!(/\B#{?o*n}/,?f*n);"#$`".size},->n,s{$m[n,s]=?o*s}

Giống như câu trả lời của MegaTom, nhưng sử dụng một chuỗi thay vì một mảng để lưu trữ trạng thái. Ký tự "o" biểu thị một ô mở, trong khi "f" biểu thị một ô được điền. Điều này cho phép chúng tôi sử dụng các hàm thao tác chuỗi tương đối ngắn gọn của Ruby:

?o*n khởi tạo một chuỗi n "o" s.

/\B#{?o*n}/là một biểu thức chính quy khớp với n "o" liên tiếp không bao gồm ký tự đầu tiên. sub!thay thế trận đấu đầu tiên bằng n "f" s.

"#$`" đưa chuỗi bên trái của trận đấu hoặc chuỗi trống nếu không có kết quả khớp, vì vậy kích thước là chỉ số được phân bổ hoặc 0.

Deallocate chỉ đặt phần được chỉ định của chuỗi trở lại "o" s.


4

JavaScript (ES6), 88

Sử dụng một biến toàn cục _(một mảng rất thưa thớt) để theo dõi.

Bây giờ làm thế nào tôi có thể kiểm tra nó?

I=n=>(_=[1],_[n]=0)
A=n=>_.some((x,i)=>i-p<n?(p=i+x,0):_[p]=n,p=1)?p:0
D=p=>delete _[p]

3

Ruby, 135

Có một mảng toàn cầu theo dõi xem mỗi ô có được phân bổ hay không.

i=->n{$a=[!0]*n;$a[0]=0}
a=->n{s=$a.each_cons(n).to_a.index{|a|a.none?};n.times{|i|$a[s+i]=0}if s;s||0}
d=->s,n{n.times{|i|$a[s+i]=!0}}

1

Toán học, 152

i=(n=#;l={{0,1},{#,#}};)&
a=If[#=={},0,l=l~Join~#;#[[1,1]]]&@Cases[l,{Except@n,e_}:>{e,e+#}/;Count[l,{a_,_}/;e<=a<e+#]<1,1,1]&
d=(l=l~DeleteCases~{#,_};)&

nlưu trữ tổng kích thước, llưu trữ trạng thái nội bộ. Bộ cấp phát sẽ cố gắng phân bổ ngay phía sau một phần khác của bộ nhớ được phân bổ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.