curl/curl ยท critical

error allocating transfer structs

Error message

error allocating transfer structs

What it means

Printed in http2-download.c:213-216 when calloc(num_transfers, sizeof(*trans)) returns NULL, i.e. the allocation of the array of struct transfer descriptors failed. This is a hard out-of-memory condition: the program cannot proceed and jumps to the cleanup label. num_transfers comes from argv[1] (clamped to 1..1000, default 3).

Source

Thrown at docs/examples/http2-download.c:214

  int still_running = 0; /* keep number of running handles */
  int num_transfers;

  if(argc > 1) {
    /* if given a number, do that many transfers */
    num_transfers = atoi(argv[1]);
    if((num_transfers < 1) || (num_transfers > 1000))
      num_transfers = 3; /* a suitable low default */
  }
  else
    num_transfers = 3; /* a suitable low default */

  result = curl_global_init(CURL_GLOBAL_ALL);
  if(result != CURLE_OK)
    return (int)result;

  trans = calloc(num_transfers, sizeof(*trans));
  if(!trans) {
    fprintf(stderr, "error allocating transfer structs\n");
    goto error;
  }

  /* init a multi stack */
  multi = curl_multi_init();
  if(!multi)
    goto error;

  for(i = 0; i < num_transfers; i++) {
    if(setup(&trans[i], i)) {
      goto error;
    }

    /* add the individual transfer */
    curl_multi_add_handle(multi, trans[i].curl);
  }

  curl_multi_setopt(multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);

View on GitHub (pinned to 527573490e)

Solutions

  1. Reduce num_transfers (the first CLI argument) to a smaller value.
  2. Raise available memory / container memory limits.
  3. Check errno (ENOMEM) and free other allocations before retrying.
  4. On 32-bit, ensure num_transfers * sizeof(*trans) does not overflow.

Example fix

// before
trans = calloc(num_transfers, sizeof(*trans));
if(!trans) {
  fprintf(stderr, "error allocating transfer structs\n");
  goto error;
}

// after - fall back to a smaller batch and report the cause
trans = calloc(num_transfers, sizeof(*trans));
if(!trans) {
  fprintf(stderr, "error allocating %d transfer structs: %s\n",
          num_transfers, strerror(errno));
  goto error;
}
Defensive patterns

Strategy: validation

Validate before calling

/* Bound and overflow-check the count before calloc. */
int n = (argc > 1) ? atoi(argv[1]) : 3;
if(n < 1 || n > 1000) n = 3;                    /* clamp like the example */
if((size_t)n > SIZE_MAX / sizeof(struct transfer)) return 1; /* overflow */

Type guard

/* Guard: num_transfers is a positive, bounded integer. */
static int sane_count(int n) { return n >= 1 && n <= 1000; }
if(!sane_count(num_transfers)) num_transfers = 3;

Try / catch

trans = calloc((size_t)num_transfers, sizeof(*trans));
if(!trans) {
  fprintf(stderr, "error allocating transfer structs\n");
  goto error;   /* nothing to free here; clean up multi/global downstream */
}

Prevention

When it happens

Trigger: malloc/calloc returning NULL due to memory exhaustion; requesting an extremely large num_transfers near the upper clamp of 1000 on a constrained system; running under cgroup memory limits that deny the allocation; calloc overflow guard tripping (sizeof(*trans) * num_transfers exceeds SIZE_MAX).

Common situations: Container/pod with low memory limits; embedded device with little RAM; passing a huge number as the first argument; running alongside a memory-hungry process; 32-bit build where address space is limited.

Related errors


AI-assisted analysis of curl/curl@527573490e (2026-08-01). Data as JSON: /data/errors/3472e21381fc0ae8.json. Report an issue: GitHub.