运行 使用 malloc 进行内存管理

memory management using malloc while running

下面是我的C程序:

int main(int argc, const char *const *argv) {

  char **upArgs = manipulate(argc, argv, toupper);
  char **lowArgs = manipulate(argc, argv, tolower);

  for (char *const *p = upArgs, *const *q = lowArgs; *p && *q; ++argv, ++p, ++q) {
    printf("[%s] -> [%s] [%s]\n", *argv, *p, *q);
  }
  free_args(upArgs, lowArgs, NULL);
}


char **manipulate(int argc, const char *const *argv, int (*const change)(int)){
    
    char **retArr = malloc((argc+1) * sizeof(char*));

    for (int i = 0; i < argc; ++i) {

        const char *const str = argv[i];
        size_t len = strlen(str);

        char* modified = malloc((len+1) * sizeof(char));

        for (size_t j = 0; j < (len+1); ++j) {
            modified[j] = change(str[j]);
        }
        retArr[i] = modified;
   } 
   return retArr;
}


 void free_args(char **args, ...){
    va_list arg;
    
    va_start(arg, args);
    for(int i =0;i < **args; i++){
        char *ar = va_arg(arg, char*);
        free(ar);
    }
    
    va_end(arg);
}


当我 运行 "leaks -atExit -- ./test" 时没有内存泄漏。
但是当我 运行 "./test" 我得到以下错误。

malloc:对象 0x7f95324059c8 的 *** 错误:未分配正在释放的指针

我的内存分配哪里出错了?

**args 不是传递给 free_args 的参数数量。您正在使用 NULL 标记来指示参数的结尾,因此您应该检查一下。

此外,参数的类型是char**,而不是char*

循环参数时,您需要从 args 开始,然后使用 va_arg 获取额外的参数。

void free_args(char **args, ...){
    va_list arg;
    
    va_start(arg, args);
    for (char **ar = args; ar != NULL; ar = va_arg(arg, char**)) {
        free(ar);
    }   
    va_end(arg);
}

请注意,此 确实 存在内存泄漏。您正在释放 upArgslowArgs 数组,但没有释放它们指向的所有字符串。我没有展示如何解决这个问题,我认为这是故意的,以便 leak 报告问题。

当我使用

leaks --atExit -- ./testleaks a Bcd EF

我收到以下泄漏报告:

Process 30435: 8 leaks for 128 total leaked bytes.

    8 (128 bytes) << TOTAL >>
      1 (16 bytes) ROOT LEAK: 0x13f606880 [16]
      1 (16 bytes) ROOT LEAK: 0x13f606890 [16]
      1 (16 bytes) ROOT LEAK: 0x13f6068a0 [16]
      1 (16 bytes) ROOT LEAK: 0x13f6068b0 [16]
      1 (16 bytes) ROOT LEAK: 0x13f6068f0 [16]
      1 (16 bytes) ROOT LEAK: 0x13f606900 [16]
      1 (16 bytes) ROOT LEAK: 0x13f606910 [16]
      1 (16 bytes) ROOT LEAK: 0x13f606920 [16]