Hệ thống brk () gọi để làm gì?


184

Theo hướng dẫn lập trình viên Linux:

brk () và sbrk () thay đổi vị trí ngắt chương trình, xác định kết thúc phân đoạn dữ liệu của quy trình.

Phân đoạn dữ liệu có ý nghĩa gì ở đây? Có phải chỉ là phân đoạn dữ liệu hoặc dữ liệu, BSS và heap kết hợp?

Theo wiki:

Đôi khi, các vùng dữ liệu, BSS và vùng heap được gọi chung là "phân đoạn dữ liệu".

Tôi thấy không có lý do để thay đổi kích thước của chỉ phân đoạn dữ liệu. Nếu đó là dữ liệu, BSS và heap tập thể thì có nghĩa là heap sẽ có nhiều không gian hơn.

Điều này đưa tôi đến câu hỏi thứ hai của tôi. Trong tất cả các bài báo tôi đọc cho đến nay, tác giả nói rằng đống lớn lên và chồng tăng dần xuống. Nhưng những gì họ không giải thích là những gì xảy ra khi đống chiếm hết không gian giữa đống và đống?

nhập mô tả hình ảnh ở đây


1
Vậy bạn sẽ làm gì khi hết chỗ? bạn đổi sang ổ cứng. Khi bạn đã sử dụng không gian, bạn phát hành nó cho các loại thông tin khác.
Igoris Azanovas

28
@Igoris: Bạn đang nhầm lẫn bộ nhớ vật lý (mà bạn có thể trao đổi sang đĩa khi cần, sử dụng bộ nhớ ảo) và không gian địa chỉ . Khi bạn điền vào không gian địa chỉ của bạn, không có sự hoán đổi nào sẽ trả lại cho bạn những địa chỉ đó ở giữa.
Daniel Pryden

7
Cũng như một lời nhắc nhở, brk()cuộc gọi hệ thống hữu ích hơn trong ngôn ngữ lắp ráp so với C. Trong C, malloc()nên được sử dụng thay vì brk()cho bất kỳ mục đích phân bổ dữ liệu nào - nhưng điều này không làm mất hiệu lực câu hỏi được đề xuất theo bất kỳ cách nào.
alecov

2
@Brian: Heap là một cấu trúc dữ liệu phức tạp để xử lý các vùng có kích thước và sự sắp xếp khác nhau, nhóm miễn phí, v.v ... Các ngăn xếp luồng luôn nằm liền kề (trong không gian địa chỉ ảo) của các trang hoàn chỉnh. Trong hầu hết các hệ điều hành, có một bộ cấp phát trang nằm dưới các ngăn xếp, heap và các tệp ánh xạ bộ nhớ.
Ben Voigt

2
@Brian: Ai nói có "Stack" nào bị thao túng bởi brk()sbrk()? Các ngăn xếp được quản lý bởi bộ cấp phát trang, ở mức thấp hơn nhiều.
Ben Voigt

Câu trả lời:


231

Trong sơ đồ mà bạn đã đăng, địa chỉ "phá vỡ" đã bị thao túng bởi brksbrklà đường chấm chấm ở đầu heap.

hình ảnh đơn giản của bố trí bộ nhớ ảo

Tài liệu bạn đã đọc mô tả đây là phần cuối của "phân đoạn dữ liệu" bởi vì trong các thư viện truyền thống (chia sẻ trước, trước mmap), phân đoạn dữ liệu liên tục với heap; trước khi chương trình bắt đầu, kernel sẽ tải các khối "văn bản" và "dữ liệu" vào RAM bắt đầu từ địa chỉ 0 (thực tế là một chút trên địa chỉ 0, để con trỏ NULL thực sự không trỏ đến bất cứ thứ gì) và đặt địa chỉ ngắt thành kết thúc phân đoạn dữ liệu. Cuộc gọi đầu tiên mallocsau đó sẽ sử dụng sbrkđể di chuyển phần chia nhỏ và tạo vùng heap ở giữa đỉnh của phân đoạn dữ liệu và địa chỉ ngắt mới, cao hơn, như được hiển thị trong sơ đồ và sử dụng tiếp theo mallocsẽ sử dụng nó để làm cho heap lớn hơn khi cần thiết

Trong khi đó, ngăn xếp bắt đầu từ đỉnh bộ nhớ và phát triển xuống. Ngăn xếp không cần các cuộc gọi hệ thống rõ ràng để làm cho nó lớn hơn; hoặc nó bắt đầu với số lượng RAM được phân bổ cho nó nhiều nhất có thể (đây là cách tiếp cận truyền thống) hoặc có một vùng địa chỉ dành riêng bên dưới ngăn xếp, mà hạt nhân sẽ tự động phân bổ RAM khi nhận thấy nỗ lực ghi vào đó (đây là cách tiếp cận hiện đại). Dù bằng cách nào, có thể có hoặc không có một khu vực "bảo vệ" ở dưới cùng của không gian địa chỉ có thể được sử dụng cho ngăn xếp. Nếu khu vực này tồn tại (tất cả các hệ thống hiện đại làm điều này) thì nó sẽ không bị phá hủy vĩnh viễn; nếu một trong haingăn xếp hoặc đống cố gắng phát triển vào nó, bạn gặp lỗi phân đoạn. Tuy nhiên, theo truyền thống, hạt nhân không cố gắng thực thi một ranh giới; ngăn xếp có thể phát triển thành đống, hoặc đống có thể phát triển thành ngăn xếp, và bằng cách nào đó, họ sẽ viết nguệch ngoạc dữ liệu của nhau và chương trình sẽ sụp đổ. Nếu bạn rất may mắn nó sẽ sụp đổ ngay lập tức.

Tôi không chắc số 512GB trong sơ đồ này đến từ đâu. Nó ngụ ý một không gian địa chỉ ảo 64 bit, không phù hợp với bản đồ bộ nhớ rất đơn giản mà bạn có ở đó. Một không gian địa chỉ 64 bit thực sự trông giống như thế này:

không gian địa chỉ ít đơn giản hóa

              Legend:  t: text, d: data, b: BSS

Đây không phải là quy mô từ xa, và nó không nên được hiểu là chính xác như bất kỳ hệ điều hành nào được đưa ra (sau khi tôi vẽ nó, tôi phát hiện ra rằng Linux thực sự đặt tệp thực thi gần với địa chỉ hơn tôi nghĩ và các thư viện chia sẻ tại địa chỉ cao đáng ngạc nhiên). Các vùng màu đen của sơ đồ này không được ánh xạ - bất kỳ quyền truy cập nào cũng gây ra sự phân tách ngay lập tức - và chúng có liên quan rất lớn đến các vùng màu xám. Các vùng màu xám nhạt là chương trình và các thư viện dùng chung của nó (có thể có hàng tá thư viện dùng chung); mỗi người có một độc lậpphân đoạn văn bản và dữ liệu (và phân đoạn "bss", cũng chứa dữ liệu toàn cầu nhưng được khởi tạo thành all-bit-zero thay vì chiếm không gian trong tệp thực thi hoặc thư viện trên đĩa). Heap không còn nhất thiết phải liên tục với phân đoạn dữ liệu của tệp thực thi - tôi đã vẽ nó theo cách đó, nhưng có vẻ như Linux, ít nhất, không làm điều đó. Ngăn xếp không còn được gắn vào đầu không gian địa chỉ ảo và khoảng cách giữa đống và ngăn xếp quá lớn đến nỗi bạn không phải lo lắng về việc vượt qua nó.

Sự phá vỡ vẫn là giới hạn trên của đống. Tuy nhiên, điều tôi không thể hiện là có thể có hàng tá phân bổ bộ nhớ độc lập ngoài kia trong màu đen ở đâu đó, được thực hiện mmapthay vì brk. (HĐH sẽ cố gắng để những thứ này cách xa brkkhu vực để chúng không va chạm.)


7
+1 để được giải thích chi tiết. Bạn có biết nếu mallocvẫn dựa vào brkhoặc nếu nó đang sử dụng mmapđể có thể "trả lại" các khối bộ nhớ riêng biệt?
Anders Abel

18
Nó phụ thuộc vào việc triển khai cụ thể, nhưng IIUC rất nhiều mallocs hiện tại sử dụng brkdiện tích cho phân bổ nhỏ và mmaps riêng cho phân bổ lớn (giả sử,> 128K). Xem, ví dụ, thảo luận về MMAP_THRESHOLD trong trang chủ Linux malloc(3).
zwol

1
Quả thực là một lời giải thích tốt. Nhưng như bạn đã nói, Stack không còn ngồi ở đầu không gian địa chỉ ảo. Điều này chỉ đúng với không gian địa chỉ 64 bit hay nó đúng ngay cả với không gian địa chỉ 32 bit. Và nếu ngăn xếp nằm ở trên cùng của không gian địa chỉ, thì bản đồ bộ nhớ ẩn danh xảy ra ở đâu? Có phải nó ở trên cùng của không gian địa chỉ ảo ngay trước khi ngăn xếp.
nik

3
@Nikhil: thật phức tạp. Hầu hết các hệ thống 32 bit đặt ngăn xếp ở trên cùng của không gian địa chỉ chế độ người dùng , thường chỉ là 2 hoặc 3G thấp hơn của không gian địa chỉ đầy đủ (không gian còn lại được dành cho kernel). Hiện tại tôi không thể nghĩ ra cái nào không nhưng tôi không biết tất cả. Hầu hết các CPU 64 bit không thực sự cho phép bạn sử dụng toàn bộ không gian 64 bit; 10 đến 16 bit cao của địa chỉ phải là 0 hoặc tất cả một. Ngăn xếp thường được đặt gần đầu của các địa chỉ thấp có thể sử dụng. Tôi không thể cho bạn một quy tắc cho mmap; nó cực kỳ phụ thuộc vào hệ điều hành.
zwol

3
@RiccardoBestetti Nó lãng phí không gian địa chỉ , nhưng điều đó vô hại - một không gian địa chỉ ảo 64 bit lớn đến mức nếu bạn đốt cháy một gigabyte của nó mỗi giây, bạn vẫn sẽ mất 500 năm để hết. [1] Hầu hết các bộ xử lý thậm chí không cho phép sử dụng nhiều hơn 2 ^ 48 đến 2 ^ 53 bit địa chỉ ảo (ngoại lệ duy nhất tôi biết là POWER4 ở chế độ bảng băm). Nó không lãng phí RAM vật lý; các địa chỉ không sử dụng không được gán cho RAM.
zwol

26

Ví dụ runnable tối thiểu

Hệ thống brk () gọi để làm gì?

Yêu cầu kernel cho phép bạn đọc và ghi vào một đoạn bộ nhớ liền kề được gọi là heap.

Nếu bạn không hỏi, nó có thể khiến bạn bối rối.

Không có brk:

#define _GNU_SOURCE
#include <unistd.h>

int main(void) {
    /* Get the first address beyond the end of the heap. */
    void *b = sbrk(0);
    int *p = (int *)b;
    /* May segfault because it is outside of the heap. */
    *p = 1;
    return 0;
}

Với brk:

#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>

int main(void) {
    void *b = sbrk(0);
    int *p = (int *)b;

    /* Move it 2 ints forward */
    brk(p + 2);

    /* Use the ints. */
    *p = 1;
    *(p + 1) = 2;
    assert(*p == 1);
    assert(*(p + 1) == 2);

    /* Deallocate back. */
    brk(b);

    return 0;
}

GitHub ngược dòng .

Ở trên có thể không có trang mới và không segfault ngay cả khi không có brk, vì vậy đây là phiên bản tích cực hơn phân bổ 16MiB và rất có khả năng segfault mà không có brk:

#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>

int main(void) {
    void *b;
    char *p, *end;

    b = sbrk(0);
    p = (char *)b;
    end = p + 0x1000000;
    brk(end);
    while (p < end) {
        *(p++) = 1;
    }
    brk(b);
    return 0;
}

Đã thử nghiệm trên Ubuntu 18.04.

Trực quan hóa không gian địa chỉ ảo

Trước brk:

+------+ <-- Heap Start == Heap End

Sau brk(p + 2):

+------+ <-- Heap Start + 2 * sizof(int) == Heap End 
|      |
| You can now write your ints
| in this memory area.
|      |
+------+ <-- Heap Start

Sau brk(b):

+------+ <-- Heap Start == Heap End

Để hiểu rõ hơn về không gian địa chỉ, bạn nên làm quen với phân trang: Làm thế nào để phân trang x86 hoạt động? .

Tại sao chúng ta cần cả hai brksbrk?

brktất nhiên có thể được thực hiện với sbrk+ tính toán bù, cả hai tồn tại chỉ để thuận tiện.

Trong phần phụ trợ, nhân Linux v5.0 có một lệnh gọi hệ thống duy nhất brkđược sử dụng để thực hiện cả hai: https://github.com/torvalds/linux/blob/v5.0/arch/x86/entry/syscalls/syscall_64. tbl # L23

12  common  brk         __x64_sys_brk

brkPOSIX?

brkđã từng là POSIX, nhưng nó đã bị xóa trong POSIX 2001, do đó cần phải _GNU_SOURCEtruy cập trình bao bọc glibc.

Việc loại bỏ có thể là do phần giới thiệu mmap, đây là một superset cho phép nhiều phạm vi được phân bổ và nhiều tùy chọn phân bổ hơn.

Tôi nghĩ rằng không có trường hợp hợp lệ mà bạn nên sử dụng brkthay vì mallochoặc mmapngày nay.

brk đấu với malloc

brklà một khả năng cũ của việc thực hiện malloc.

mmaplà cơ chế mạnh mẽ hơn mới hơn mà có khả năng tất cả các hệ thống POSIX hiện đang sử dụng để thực hiện malloc. Dưới đây là một ví dụ phân bổ bộ nhớ runnable tối thiểummap .

Tôi có thể trộn brkvà malloc không?

Nếu bạn mallocđược thực hiện cùng brk, tôi không biết làm thế nào điều đó có thể không làm nổ tung mọi thứ, vì brkchỉ quản lý một phạm vi bộ nhớ duy nhất.

Tuy nhiên tôi không thể tìm thấy bất cứ điều gì về nó trên các tài liệu glibc, ví dụ:

Mọi thứ có thể sẽ chỉ hoạt động ở đó tôi cho rằng vì mmapcó khả năng được sử dụng cho malloc.

Xem thêm:

Thêm thông tin

Trong nội bộ, kernel quyết định xem tiến trình có thể có nhiều bộ nhớ đó không và đánh dấu các trang bộ nhớ cho việc sử dụng đó.

Điều này giải thích cách ngăn xếp so sánh với heap: Chức năng của các lệnh đẩy / pop được sử dụng trên các thanh ghi trong cụm x86 là gì?


4
plà một con trỏ để gõ int, nên đây không phải là brk(p + 2);?
Johan Boulé

Lưu ý nhỏ: Biểu thức trong vòng lặp for của phiên bản tích cực có lẽ phải là*(p + i) = 1;
lima.sierra 14/11/18

Nhân tiện, tại sao chúng ta cần sử dụng brk(p + 2)thay vì chỉ đơn giản là tăng nó bằng cách sbrk(2)? Là brk thực sự cần thiết?
Yi Lin Liu

1
@YiLinLiu Tôi nghĩ rằng đó chỉ là hai giao diện C rất giống nhau cho một phụ trợ nhân đơn ( brksyscall). brksẽ thuận tiện hơn một chút để khôi phục ngăn xếp được phân bổ trước đó.
Ciro Santilli 郝海东 冠状 病 事件 法轮功

1
@CiroSantilli 改造 心 心 6 8 - (2 * sizeof int)). Không nên trỏ đến bộ lưu trữ heap có sẵn tiếp theo - sẽ cách 4 byte (không phải 8). Chỉnh sửa cho tôi nếu tôi thiếu một cái gì đó ở đây.
Saket Sharad

10

Bạn có thể sử dụng brksbrkchính mình để tránh "malloc trên đầu" mọi người luôn phàn nàn. Nhưng bạn không thể dễ dàng sử dụng phương pháp này để kết hợp với mallocnó vì vậy nó chỉ phù hợp khi bạn không phải làm freegì cả. Bởi vì bạn không thể. Ngoài ra, bạn nên tránh mọi cuộc gọi thư viện có thể sử dụng mallocnội bộ. I E. strlencó lẽ là an toàn, nhưng fopencó lẽ là không.

Gọi sbrkgiống như bạn sẽ gọi malloc. Nó trả về một con trỏ đến dấu ngắt hiện tại và tăng số lần ngắt theo số tiền đó.

void *myallocate(int n){
    return sbrk(n);
}

Mặc dù bạn không thể giải phóng các phân bổ riêng lẻ (vì không có phí trung tâm , hãy nhớ), bạn có thể giải phóng toàn bộ không gian bằng cách gọi brkvới giá trị được trả về bởi cuộc gọi đầu tiên sbrk, do đó tua lại brk .

void *memorypool;
void initmemorypool(void){
    memorypool = sbrk(0);
}
void resetmemorypool(void){
    brk(memorypool);
}

Bạn thậm chí có thể xếp chồng các khu vực này, loại bỏ khu vực gần đây nhất bằng cách tua lại thời gian nghỉ để bắt đầu khu vực.


Một điều nữa ...

sbrkcũng hữu ích trong mã golf vì nó ngắn hơn 2 ký tự malloc.


7
-1 vì: malloc/ freechắc chắn nhất có thể (và làm) trả lại bộ nhớ cho HĐH. Họ có thể không luôn luôn làm điều đó khi bạn muốn, nhưng đó là vấn đề của các heuristic được điều chỉnh không hoàn hảo cho trường hợp sử dụng của bạn. Quan trọng hơn, sẽ không an toàn khi gọi sbrkvới một đối số khác không trong bất kỳ chương trình nào có thể gọi malloc- và hầu như tất cả các chức năng của thư viện C đều được phép gọi mallocnội bộ. Những thứ duy nhất chắc chắn sẽ không là các chức năng an toàn tín hiệu async .
zwol

Và bởi "nó không an toàn", ý tôi là "chương trình của bạn sẽ bị sập".
zwol

Tôi đã chỉnh sửa để loại bỏ bộ nhớ quay trở lại và đề cập đến sự nguy hiểm của các chức năng thư viện trong nội bộ malloc.
luser droog

1
Nếu bạn muốn thực hiện cấp phát bộ nhớ ưa thích, hãy căn cứ vào đỉnh của malloc hoặc trên đỉnh của mmap. Đừng chạm vào brk và sbrk, chúng là những di vật từ quá khứ gây hại nhiều hơn lợi (thậm chí các trang web còn nói với bạn hãy tránh xa chúng!)
Eloff

3
Điều này thật ngốc nghếch. Nếu bạn muốn tránh việc sử dụng malloc cho nhiều phân bổ nhỏ, hãy thực hiện một phân bổ lớn (với malloc hoặc mmap, không phải sbrk) và tự mình loại bỏ nó. Nếu bạn giữ các nút của cây nhị phân của mình trong một mảng, bạn có thể sử dụng các chỉ mục 8b hoặc 16b thay vì con trỏ 64b. Điều này hoạt động rất tốt khi bạn không phải xóa bất kỳ nút nào cho đến khi bạn sẵn sàng xóa tất cả các nút. (ví dụ: xây dựng một từ điển được sắp xếp một cách nhanh chóng.) Sử dụng sbrkcho việc này chỉ hữu ích cho môn đánh gôn, bởi vì sử dụng thủ công mmap(MAP_ANONYMOUS)sẽ tốt hơn về mọi mặt ngoại trừ kích thước mã nguồn.
Peter Cordes

3

Có một ánh xạ bộ nhớ riêng ẩn danh được chỉ định đặc biệt (theo truyền thống nằm ngay ngoài dữ liệu / bss, nhưng Linux hiện đại sẽ thực sự điều chỉnh vị trí với ASLR). Về nguyên tắc nó không có gì tốt hơn so với bất kỳ bản đồ khác mà bạn có thể tạo ra với mmap, nhưng Linux có một số tối ưu hóa mà làm cho nó có thể mở rộng đến cuối bản đồ này (sử dụng brksyscall) trở lên với chi phí giảm khóa liên quan đến những gì mmaphoặc mremapsẽ phải chịu. Điều này làm cho nó hấp dẫn để malloctriển khai sử dụng khi thực hiện heap chính.


Bạn có nghĩa là có thể mở rộng phần cuối của ánh xạ này lên, đúng không?
zwol

Có, đã sửa. Xin lỗi vì điều đó!
R .. GitHub DỪNG GIÚP ICE

0

Tôi có thể trả lời câu hỏi thứ hai của bạn. Malloc sẽ thất bại và trả về một con trỏ null. Đó là lý do tại sao bạn luôn kiểm tra con trỏ null khi cấp phát bộ nhớ động.


Vậy thì việc sử dụng brk và sbrk là gì?
nik

3
@NikhilRathod: malloc()sẽ sử dụng brk()và / hoặc sbrk()dưới mui xe - và bạn cũng có thể, nếu bạn muốn triển khai phiên bản tùy chỉnh của riêng mình malloc().
Daniel Pryden

@Daniel Pryden: làm thế nào brk và sbrk có thể hoạt động trên heap khi nó nằm giữa ngăn xếp và phân đoạn dữ liệu như trong sơ đồ trên. cho việc này để làm việc đống nên cuối cùng. Tôi có đúng không
nik

2
@Brian: Daniel nói rằng HĐH quản lý phân đoạn ngăn xếp chứ không phải con trỏ ngăn xếp ... những thứ rất khác nhau. Vấn đề là không có tòa nhà sbrk / brk cho phân đoạn ngăn xếp - Linux tự động phân bổ các trang khi cố gắng ghi vào cuối phân đoạn ngăn xếp.
Jim Balter

1
Và Brian, bạn chỉ trả lời một nửa câu hỏi. Nửa còn lại là những gì xảy ra nếu bạn cố gắng đẩy lên ngăn xếp khi không còn chỗ trống ... bạn gặp lỗi phân đoạn.
Jim Balter

0

Heap được đặt cuối cùng trong phân đoạn dữ liệu của chương trình. brk()được sử dụng để thay đổi (mở rộng) kích thước của heap. Khi heap không thể tăng thêm nữa, bất kỳ malloccuộc gọi nào cũng sẽ thất bại.


Vì vậy, bạn đang nói rằng tất cả các sơ đồ trên internet, giống như trong câu hỏi của tôi là sai. Nếu có thể bạn có thể vui lòng chỉ cho tôi một sơ đồ chính xác.
nik

2
@Nikkhil Hãy nhớ rằng đỉnh của sơ đồ đó là phần cuối của bộ nhớ. Đỉnh của ngăn xếp di chuyển xuống trên sơ đồ khi ngăn xếp phát triển. Đỉnh của heap di chuyển lên trên sơ đồ khi nó được mở rộng.
Brian Gordon

0

Phân đoạn dữ liệu là phần bộ nhớ chứa tất cả dữ liệu tĩnh của bạn, được đọc từ tệp thực thi khi khởi chạy và thường không chứa đầy.


Nó cũng chứa dữ liệu tĩnh chưa được khởi tạo (không có trong tệp thực thi) có thể là rác.
luser droog

Dữ liệu tĩnh chưa .bssđược khởi tạo ( ) được hệ điều hành khởi tạo thành all-bit-zero trước khi chương trình bắt đầu; điều này thực sự được đảm bảo bởi tiêu chuẩn C. Một số hệ thống nhúng có thể không làm phiền, tôi cho rằng (tôi chưa bao giờ thấy một hệ thống nào, nhưng tôi không làm việc tất cả những gì được nhúng)
zwol

@zwol: Linux có tùy chọn biên dịch theo thời gian để không trả về các trang được trả về mmap, nhưng tôi cho rằng .bssnó vẫn sẽ bằng không. Không gian BSS có lẽ là cách nhỏ gọn nhất để diễn tả thực tế rằng một chương trình muốn một số mảng zerod.
Peter Cordes

1
@PeterCordes Tiêu chuẩn C nói là các biến toàn cục được khai báo không có bộ khởi tạo được coi là - nếu được khởi tạo thành 0. Do đó, việc triển khai AC đặt các biến đó vào .bssvà không bằng 0 .bsssẽ không phù hợp. Nhưng không có gì buộc một triển khai C phải sử dụng .bsscả hoặc thậm chí có một thứ như vậy.
zwol

@PeterCordes Ngoài ra, dòng giữa "triển khai C" và chương trình có thể rất mờ, ví dụ: thường có một đoạn mã nhỏ từ việc triển khai, được liên kết tĩnh với từng tệp thực thi, chạy trước đó main; mã đó có thể thoát ra khỏi .bsskhu vực thay vì có kernel làm điều đó và điều đó vẫn sẽ tuân thủ.
zwol

0

malloc sử dụng cuộc gọi hệ thống brk để phân bổ bộ nhớ.

bao gồm

int main(void){

char *a = malloc(10); 
return 0;
}

chạy chương trình đơn giản này với strace, nó sẽ gọi hệ thống brk.

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.