{"id":"3472e21381fc0ae8","repo":"curl/curl","slug":"error-allocating-transfer-structs","errorCode":null,"errorMessage":"error allocating transfer structs\n","messagePattern":"error allocating transfer structs\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"docs/examples/http2-download.c","lineNumber":214,"sourceCode":"  int still_running = 0; /* keep number of running handles */\n  int num_transfers;\n\n  if(argc > 1) {\n    /* if given a number, do that many transfers */\n    num_transfers = atoi(argv[1]);\n    if((num_transfers < 1) || (num_transfers > 1000))\n      num_transfers = 3; /* a suitable low default */\n  }\n  else\n    num_transfers = 3; /* a suitable low default */\n\n  result = curl_global_init(CURL_GLOBAL_ALL);\n  if(result != CURLE_OK)\n    return (int)result;\n\n  trans = calloc(num_transfers, sizeof(*trans));\n  if(!trans) {\n    fprintf(stderr, \"error allocating transfer structs\\n\");\n    goto error;\n  }\n\n  /* init a multi stack */\n  multi = curl_multi_init();\n  if(!multi)\n    goto error;\n\n  for(i = 0; i < num_transfers; i++) {\n    if(setup(&trans[i], i)) {\n      goto error;\n    }\n\n    /* add the individual transfer */\n    curl_multi_add_handle(multi, trans[i].curl);\n  }\n\n  curl_multi_setopt(multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/curl/curl/blob/527573490eb2564b3d7c9dd51d8bff963b5d6303/docs/examples/http2-download.c#L196-L232","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","solutions":["Reduce num_transfers (the first CLI argument) to a smaller value.","Raise available memory / container memory limits.","Check errno (ENOMEM) and free other allocations before retrying.","On 32-bit, ensure num_transfers * sizeof(*trans) does not overflow."],"exampleFix":"// before\ntrans = calloc(num_transfers, sizeof(*trans));\nif(!trans) {\n  fprintf(stderr, \"error allocating transfer structs\\n\");\n  goto error;\n}\n\n// after - fall back to a smaller batch and report the cause\ntrans = calloc(num_transfers, sizeof(*trans));\nif(!trans) {\n  fprintf(stderr, \"error allocating %d transfer structs: %s\\n\",\n          num_transfers, strerror(errno));\n  goto error;\n}","handlingStrategy":"validation","validationCode":"/* Bound and overflow-check the count before calloc. */\nint n = (argc > 1) ? atoi(argv[1]) : 3;\nif(n < 1 || n > 1000) n = 3;                    /* clamp like the example */\nif((size_t)n > SIZE_MAX / sizeof(struct transfer)) return 1; /* overflow */","typeGuard":"/* Guard: num_transfers is a positive, bounded integer. */\nstatic int sane_count(int n) { return n >= 1 && n <= 1000; }\nif(!sane_count(num_transfers)) num_transfers = 3;","tryCatchPattern":"trans = calloc((size_t)num_transfers, sizeof(*trans));\nif(!trans) {\n  fprintf(stderr, \"error allocating transfer structs\\n\");\n  goto error;   /* nothing to free here; clean up multi/global downstream */\n}","preventionTips":["Clamp user-supplied transfer counts to a sane maximum (the example uses [1,1000]).","Guard against size_t overflow: check n <= SIZE_MAX / sizeof(struct) before calloc.","On calloc failure, degrade gracefully (fewer parallel transfers) rather than aborting.","Keep a single cleanup label so every successfully allocated resource is freed in the error path."],"tags":["memory","calloc","out-of-memory","http2","c"],"analyzedSha":"527573490eb2564b3d7c9dd51d8bff963b5d6303","analyzedAt":"2026-08-01T21:00:26.351Z","schemaVersion":2}