【问题标题】:realloc, two dimention allocation, leak and errors in valgrindrealloc,二维分配,valgrind中的泄漏和错误
【发布时间】:2021-06-24 12:05:06
【问题描述】:
  • 我写了一个程序来根据特定的分隔符分割给定的字符串。一切工作正常,但valgrind 中存在泄漏和错误

  • split算法正确。

  • substr 工作正常。

  • 我的程序

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

char** split(const char*, char, int*);
char* substr(const char*, int, int);
void freepath(char**, int);

int main(void) {
    char *str = "home///ubuntu//Desktop";
    char **path = NULL;
    int size = 0;

    path = split(str, '/', &size);

    freepath(path, size);
    return 0;   
}

char** split(const char *str, char c, int *size) {

    char **path = NULL;
    const char *save = str;
    int from=-1, i;

    if(str == NULL)
        return NULL;

    for(i=0 ; 1; ++i) {
        if(*str == '\0') {
            if(from != -1) {
                ++(*size);
                path = (char**)realloc(path, (sizeof(char**) *(*size)));
                *(path+(*size)-1) = substr(save, from, i);
            }
            break;
        }
        if(*str != '/') {
            if(from == -1)
                from = i;
        }
        else {
            if(from != -1) {
                ++(*size);
                path = (char**)realloc(path, (sizeof(char)*(*size)));
                *(path+(*size)-1) = substr(save, from, i);
            }
            from = -1;
        }
        ++str;
    }
    return path;
}

void freepath(char **path, int size) {

    int i=0;

    for(i=0; i<size; ++i) {
        free(*(path+i));
        *(path+i) = NULL;
    }
    free(path);
    path = NULL;
}


char* substr(const char *src, int m, int n)
{
    int len = n - m;
    char *dest = (char*)malloc(sizeof(char) * (len + 1));

    for (int i = m; i < n && (*(src + i) != '\0'); i++)
    {
        *dest = *(src + i);
        ++dest;
    }
    *dest = '\0';

    return dest - len;
}
  • Valgrind 输出
  • 应该是什么原因? ,我真的坚持了!

【问题讨论】:

  • substr() 看起来......片状。你在 mallocing 后改变 'dest' 。您绝对确定 substr() 总是返回您分配的指针吗?如果没有,那么你已经泄露了分配......你不能复制'dest'来返回吗?
  • split() 可以使用 strtok() 更轻松地实现。
  • BTW,*(x+i)等价于x[i],后者更容易理解。
  • path = (char**)realloc(path, (sizeof(char)*(*size))); --> 尺寸错误。试试path = realloc(path, sizeof *path * *size);
  • substr() 中的循环可以替换为strncpy()。这是实际上正确功能的少数情况之一。

标签: c split memory-leaks valgrind realloc


【解决方案1】:

clang 分析器在您的代码中发现了 4 个可疑点:

1.

char *str = "home///ubuntu//Desktop";

const 前面需要 char(指向 const 的指针)。

2.

char** split(const char *str, char c, int *size) {

包含一个未使用的参数 (c)。

3.

path = (char**)realloc(path, (sizeof(char**) *(*size)));

clang-analyser 不喜欢 char** 作为 sizeof 的参数,将其替换为 char* 会删除警告。

4.

path = (char**)realloc(path, (sizeof(char)*(*size)));

与 3 中的警告相同。错误,不,不一样。答对了!将sizeof 中的char 替换为char*,然后你就回家了。

最后一句话。使用 valgrind 时,始终在编译后的代码中添加调试信息,即在编译器命令行选项(gcc、clang 等)中添加-g。这将为您提供有关源代码中与 valgrind 发现问题的位置相对应的确切行号的信息。我在 valgrind 下的程序截图包含的信息比你的多:

请注意,valgrind 正确地将第 44 行识别为内存分配错误的行(或第 45 行,第 44 行分配的缓冲区使用错误。这两个选项都是先验可能正确的)。

【讨论】:

  • clang-analyser 不喜欢char** 作为sizeof 的参数,这很奇怪,但是用void* 替换它可以消除警告sizeof 中的char 替换为void*?!?不可以。一般不能保证指针与void * 的大小相同。仅仅用 void * 替换指针来覆盖警告是一个非常糟糕的主意。
  • @AndrewHenle 好吧,好吧,你是对的,指针可能有不同的长度,它取决于实现。
  • @AndrewHenle 我编辑了答案。 Clang-analyser 是对的:如果我们需要指向 char* 的指针,只有 char* 是可以的。
  • 好的,我会尝试修复并反馈结果。
猜你喜欢
  • 2014-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多