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

C语言动态内存分配字符串构建器实现及代码优化咨询

C语言动态字符串构建器实现与优化

我在C语言中实现动态内存分配的字符串构建器时遇到了一些问题,以下是初始实现代码及使用示例:

初始代码

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

void *alloc(void **ptr, size_t len) {
  free(*ptr);
  void *mem = malloc(len);
  if (mem == NULL) {
    fprintf(stderr, "err: alloc failed");
    exit(EXIT_FAILURE);
  }
  return mem;
}

char *str(char **src, const char *fmt, ...) {
  if (fmt == NULL) {
    return NULL;
  }
  va_list args;
  va_start(args, fmt);
  size_t len = vsnprintf(NULL, 0, fmt, args);
  if (len < 0) {
    return NULL;
  }
  *src = alloc((void **) src, sizeof(char) * (len + 1));
  vsnprintf(*src, len + 1, fmt, args);
  va_end(args);
  return *src;
}

初始使用示例

int main(int argc, char *argv[]) {
  char *s = str(&s, "FOUND!");
  puts(s);
  puts(str(&s, "NOT %s", s));
  puts(s);
  return 0;
}

疑问点

  • 代码是否存在内存泄漏?
  • 动态内存分配操作是否有误?
  • 使用str(&pointer, "value")初始化char *时,传递未初始化指针的地址是否合理?

修改后代码

根据相关建议,我对代码进行了调整,修改后的代码如下:

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

void *alloc(void *ptr, size_t len) {
  void *mem = realloc(ptr, len);
  if (mem == NULL) {
    free(ptr);
    perror(NULL);
  }
  return mem;
}

char *str(char *src, const char *fmt, ...) {
  if (fmt == NULL) {
    return NULL;
  }
  va_list args1, args2;
  va_copy(args2, args1);
  va_start(args1, fmt);
  int len = vsnprintf(NULL, 0, fmt, args1);
  va_end(args1);
  if (len < 0) {
    return NULL;
  }
  char *val = alloc(src, len + 1);
  va_start(args2, fmt);
  int res = vsnprintf(val, len + 1, fmt, args2);
  va_end(args2);
  free(src);
  if (res < 0) {
    free(val);
    return NULL;
  }
  return val;
}

int main(int argc, char *argv[]) {
  char *s = str(NULL, "FOUND!");
  puts(s);
  free(s);
  s = str(s, "NOT %s", s);
  puts(s);
  free(s);
  return 0;
}

修改要点

  • N: 传递未初始化的&pointer是错误的,属于隐性错误。
  • N: 使用realloc替代malloc,它可处理NULL初始值并释放之前分配的内存。
  • 将**参数改为*,最初使用**是为了在函数内直接修改*src指针的值(原代码中该逻辑生效)。
  • 初始声明改为char *s = str(NULL, "value"),更新值时需重新赋值s = str(s, "updated: %s", s)。
  • 将vsnprintf返回值的类型从size_t改为int,最初使用size_t是为了匹配malloc的size_t参数。
  • N: 第二次调用vsnprintf的结果可能与第一次不同,因此使用va_copy复制第一个va_list用于第二次调用。
  • 返回实际值前释放旧字符串。

待确认问题

希望确认修改后的代码是否仍存在问题,以及是否有进一步的优化方向。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:50:39