You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移动指针缩短字符串并正确释放内存?含大数相加场景

C语言字符串末尾填充与内存释放问题解决

为什么会出现free(): invalid pointer错误?

你传给free的指针不是calloc返回的原始内存起始地址。
在你的代码中,res一开始指向calloc分配的10字节内存首地址,但执行res++后,指针被移动到了数组第5个字节的位置。C语言内存管理规则要求:只有malloc/calloc/realloc返回的原始指针才能被free,移动后的指针不属于合法释放对象,因此触发错误。

修复当前代码的两种方法

方法1:保留原始指针,将有效内容移到缓冲区开头

保存calloc返回的原始指针,找到有效字符串的起始位置后,把内容拷贝到缓冲区开头,返回原始指针即可正常释放:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char* getGreeting() {
  // 保存原始分配的指针
  char* original_res = (char*) calloc(10, sizeof(char));
  char* res = original_res;

  // 从末尾写入字符
  res[4] = 'H';
  res[5] = 'e';
  res[6] = 'l';
  res[7] = 'l';
  res[8] = 'o';
  res[9] = '\0';

  // 找到第一个非空字符的位置
  char* start = original_res;
  while (*start == '\0') {
    start++;
  }

  // 把有效字符串拷贝到缓冲区开头
  memmove(original_res, start, strlen(start) + 1);

  // 返回原始指针,调用者可直接free
  return original_res;
}

int main() {
  char* greeting = getGreeting();
  printf("res: %s\n", greeting);
  free(greeting); // 正常释放
  return 0;
}

方法2:重新分配内存,拷贝有效内容

找到有效字符串后,用strdup(或malloc+strcpy)创建新内存块,释放原始内存,返回新指针:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char* getGreeting() {
  char* res = (char*) calloc(10, sizeof(char));

  res[4] = 'H';
  res[5] = 'e';
  res[6] = 'l';
  res[7] = 'l';
  res[8] = 'o';
  res[9] = '\0';

  char* start = res;
  while (*start == '\0') {
    start++;
  }

  // 分配新内存拷贝有效字符串
  char* result = strdup(start);
  // 释放原始内存
  free(res);

  return result;
}

int main() {
  char* greeting = getGreeting();
  printf("res: %s\n", greeting);
  free(greeting); // 正常释放
  return 0;
}

针对大数相加场景的解决方案

你的原始需求是实现十进制大数相加,从末尾填充字符串,这里推荐两种适配方案:

方案1:预分配足够内存(推荐)

大数相加的最大长度可预估:两个输入字符串的最大长度 +1(预留进位空间),直接分配足够内存即可:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char* addBigNumbers(const char* num1, const char* num2) {
    int len1 = strlen(num1);
    int len2 = strlen(num2);
    int max_len = len1 > len2 ? len1 : len2;
    // 分配内存:max_len+2(进位+结束符)
    char* buffer = calloc(max_len + 2, sizeof(char));
    if (!buffer) return NULL;

    // 指针指向缓冲区最后一个可写位置(结束符前)
    char* ptr = buffer + max_len;
    int carry = 0;
    int i = len1 - 1, j = len2 - 1;

    // 从末尾逐位相加
    while (i >= 0 || j >= 0 || carry > 0) {
        int digit1 = (i >= 0) ? (num1[i] - '0') : 0;
        int digit2 = (j >= 0) ? (num2[j] - '0') : 0;
        int sum = digit1 + digit2 + carry;
        carry = sum / 10;
        *ptr = (sum % 10) + '0';
        ptr--;
        i--;
        j--;
    }

    // 有效字符串起始位置
    char* start = ptr + 1;
    // 移到缓冲区开头
    memmove(buffer, start, strlen(start) + 1);

    return buffer;
}

int main() {
    char* result = addBigNumbers("123456789", "987654321");
    printf("Result: %s\n", result);
    free(result); // 正常释放
    return 0;
}

方案2:动态扩容(完全未知长度场景)

如果无法预估最大长度,可使用realloc动态扩容缓冲区:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char* addBigNumbersDynamic(const char* num1, const char* num2) {
    int capacity = 32;
    char* buffer = calloc(capacity, sizeof(char));
    if (!buffer) return NULL;
    char* ptr = buffer + capacity - 1; // 指向最后可写位置
    int carry = 0;
    int i = strlen(num1) - 1, j = strlen(num2) - 1;

    while (i >= 0 || j >= 0 || carry > 0) {
        // 检查缓冲区是否已满
        if (ptr == buffer) {
            int new_capacity = capacity * 2;
            // 计算当前已填充的内容长度
            int content_len = (buffer + capacity - 1) - ptr;
            // 扩容
            char* new_buffer = realloc(buffer, new_capacity);
            if (!new_buffer) {
                free(buffer);
                return NULL;
            }
            // 调整指针位置
            ptr = new_buffer + new_capacity - 1 - content_len;
            buffer = new_buffer;
            capacity = new_capacity;
        }

        int digit1 = (i >= 0) ? (num1[i] - '0') : 0;
        int digit2 = (j >= 0) ? (num2[j] - '0') : 0;
        int sum = digit1 + digit2 + carry;
        carry = sum / 10;
        *ptr = (sum % 10) + '0';
        ptr--;
        i--;
        j--;
    }

    // 补结束符,调整有效起始位置
    char* start = ptr + 1;
    memmove(buffer, start, strlen(start) + 1);
    // 可选:缩容到刚好大小
    char* result = realloc(buffer, strlen(buffer) + 1);
    return result ? result : buffer;
}

int main() {
    char* result = addBigNumbersDynamic("9999999999999999", "1");
    printf("Result: %s\n", result);
    free(result);
    return 0;
}

内容的提问来源于stack exchange,提问作者dayuloli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 19:27:51