【问题标题】:Memory issue in C where data is being overwrittenC 中的内存问题,其中数据被覆盖
【发布时间】:2011-02-20 00:13:27
【问题描述】:

我有以下程序:

// required include statements...

static char ***out;

char* get_parameter(char* key)
{
    char *querystr = /*getenv("QUERY_STRING")*/ "abcdefg=abcdefghi";
    if (querystr == NULL)
        return (void*)0;

    char s[strlen(querystr)] ;
    strcpy(s, querystr);
    const char delim = '&';
    const char delim2 = '=';
    static size_t size = 0;
    if (out == 0)
    {
        out = (char*) malloc(sizeof(char*));
        size = split(s, &delim, out);
    }

    int i=0;
    for (; i<size; i++)
    {
        if ((*out)[i] != NULL)
        {
            char ***iout = NULL;
            iout = (char*) malloc(sizeof(char*));
            int isize = split((*out)[i], &delim2, iout);

            if (isize > 1 && ((*iout)[1]) != NULL && strcmp(key, (*iout)[0]) == 0)
            {
                size_t _size = strlen((*iout)[1]);
                char* value = (char*) malloc(_size*sizeof(char));
                strcpy(value, (*iout)[1]);
                free(iout);
                return value;
            }
        }
    }
    return (void*) 0;
}

static size_t count(const char *str, char ch)
{
    if (str == NULL) return 0;
    size_t count = 1;
    while (*str)
        if (*str++ == ch) count++;
    return count;
}

size_t split(const char *const str, const char* delim, char ***out)
{
    size_t size = count(str, *delim);
    *out = calloc(size, sizeof(char));
    char* token = NULL;
    char* tmp = (char*) str;
    int i=0;
    while ((token = strtok(tmp, delim)) != NULL)
    {
        tmp = NULL;
        (*out)[i] = (char*) malloc(sizeof strlen(token));
        strcpy((*out)[i++], token);
    }
    return size;
}

main()
{
    char* val = get_parameter("abcdefg");
    printf("%s\n", val);  // it should prints `abcdefghi`, but it prints `abcd?`
    free(val);
}

如 main 方法中所示,函数 get_parameter 应该打印 abcdefghi,但它会打印 abcd?,其中 ? 是一个值为 17 的控制字符。

为什么不打印字符串的重置?我想我误用了malloc 来分配适当的空间。

另外,我可以使用任何工具来了解我的指针内存的内部表示吗?

【问题讨论】:

    标签: c memory-leaks memory-management


    【解决方案1】:

    您在这里处理的是 C 字符串。您必须考虑为 NULL 终止 ('\0') 增加 1 个字节

    因此:

    char s[strlen(querystr)] ;
    strcpy(s, querystr);
    

    不正确。

    strlen 将为字符串“abcd”返回 4,但您想要为“abcd\0”分配空间

    所以你需要 strlen + 1

    【讨论】:

    • 进行更改后仍然存在问题。以及querystr 是如何不被 NULL 终止的?我知道任何“str”都是由编译器终止的空值
    • 我已将+1 添加到所有代码中strlen 的结果中,但我仍然有问题。问题只有在我替换以下行时才解决:(*out)[i] = (char*) malloc(sizeof strlen(token));(*out)[i] = (char*) malloc(sizeof strlen(token) * sizeof(char*));
    • 您的“计数”方法错误。对于空字符串,它将返回 1,对于带有 ch '=' 的“abcd=abcd”,它将返回 2
    • 是的,我应该把它修改成str == NULL || strlen(str) == 0
    【解决方案2】:

    线条

    out = (char*) malloc(sizeof(char*));
    
    iout = (char*) malloc(sizeof(char*));
    

    是个问题。

    sizeof() 返回存储给定类型的对象所需的字节数,在本例中为指针的大小(指向char)。 malloc() 然后分配那么多字节(在您的架构上显然是 4 个字节)。要解决此问题,您需要为 malloc 提供所需的字符串长度,而不是使用 sizeof

    另外,一行

    char* value = (char*) malloc(_size*sizeof(char));
    

    完全没有必要使用sizeof()sizeof(char) 被标准保证为 1。

    【讨论】:

    • 你说的是哪一行?
    【解决方案3】:

    您应该使用 gdb 逐步运行您的二进制文件,看看有什么问题。 Valgrind 是一个非常好的工具,它会告诉你什么是内存中的行覆盖等等。

    【讨论】:

      猜你喜欢
      • 2014-05-29
      • 2022-01-26
      • 2010-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多