RLIMIT_DATA Data Segment Limit: Heap, Initialized & Uninitialized Data

 

36.3 — RLIMIT_DATA
Data Segment Limit: Heap, Initialized & Uninitialized Data | EmbeddedPathashala

What is RLIMIT_DATA?

RLIMIT_DATA limits the maximum size of the process’s data segment in bytes. The data segment is the sum of three memory regions: the initialized data segment (global variables with explicit initial values), the uninitialized data segment (BSS — global variables initialised to zero), and the heap (dynamic memory from malloc/new).

What the Data Segment Contains

Initialized Data (.data) — Global and static variables that have explicit initial values in the source code. Example: int x = 42; at file scope.
Uninitialized Data (.bss) — Global and static variables that are zero-initialized. Example: int arr[1000]; at file scope. The kernel zero-fills these at startup.
Heap — Memory dynamically allocated via malloc(), calloc(), realloc(), and new. The heap grows upward from the end of BSS as the program break (managed by brk()/sbrk()) is moved.

When the process tries to extend its data segment — via sbrk() or brk() — beyond the soft RLIMIT_DATA limit, the call fails with ENOMEM. In practice, this means malloc() and calloc() return NULL.

Code Example — RLIMIT_DATA and Heap Growth

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/resource.h>

int main(void)
{
    struct rlimit rl;
    void *ptr;
    int alloc_count = 0;

    /* Set data segment limit to 8 MB */
    rl.rlim_cur = 8 * 1024 * 1024;
    rl.rlim_max = 8 * 1024 * 1024;
    if (setrlimit(RLIMIT_DATA, &rl) == -1) {
        perror("setrlimit"); exit(1);
    }
    printf("Data segment limit set to 8 MB\n");

    /* Keep allocating 1 MB chunks until malloc fails */
    while (1) {
        ptr = malloc(1024 * 1024);  /* 1 MB */
        if (ptr == NULL) {
            printf("malloc failed after %d MB (errno=%d: %s)\n",
                   alloc_count, errno,
                   errno == ENOMEM ? "ENOMEM" : "other");
            break;
        }
        alloc_count++;
        printf("Allocated chunk %d (total ~%d MB)\n",
               alloc_count, alloc_count);
    }
    return 0;
}
/* Compile: gcc -o rlimit_data rlimit_data.c
   Note: actual failure point may vary due to existing data segment size */

Interview Questions

Q1. What three memory regions make up the data segment measured by RLIMIT_DATA?

The initialized data segment (.data) — global/static variables with explicit initial values. The uninitialized data segment (.bss) — global/static variables zero-initialized by the kernel. The heap — dynamically allocated memory from malloc()/calloc()/new. All three are summed together for the RLIMIT_DATA check.

Q2. Which system calls fail with ENOMEM when RLIMIT_DATA is exceeded?

sbrk() and brk() fail with ENOMEM. Since malloc(), calloc(), and realloc() use these internally, they return NULL when the data segment limit is hit.

Q3. What is the difference between RLIMIT_DATA and RLIMIT_AS?

RLIMIT_DATA limits only the data segment (initialized data + BSS + heap). RLIMIT_AS limits the entire virtual address space of the process, including all the above plus text, stack, memory-mapped files, and shared memory. RLIMIT_AS is the broader, more complete constraint.

Q4. Does RLIMIT_DATA count the stack?

No. The stack is a separate segment and is governed by RLIMIT_STACK, not RLIMIT_DATA.

Leave a Reply

Your email address will not be published. Required fields are marked *