增加指针后释放内存

时间:2013-07-03 05:51:12

标签: c free

gcc (GCC) 4.7.2
c89

您好,

All error checking removed from snippet - to keep the code short.

我遇到了一个问题,即释放了我已经分配的内存并将字符串复制到。

我的程序将检查数字并递增指针,直到它变为非数字。

当我去释放内存时,我得到一个无效空闲的堆栈转储。

我认为这是因为我增加了指针,现在它指向字符串的中间位置,就像非数字开始时一样。 如果我没有增加它的确定免费。但是,如果我增加它然后尝试释放我得到堆栈转储。

int parse_input(const char *input)
{
    char *cpy_input = calloc(strlen(input) + 1, sizeof(char));
    size_t i = 0;

    apr_cpystrn(cpy_input, input, strlen(input) + 1);



    /* Are we looking for a range of channels */
    for(i = 0; i < strlen(cpy_input); i++) {
        if(isdigit(*cpy_input)) {
        /* Do something here */
            cpy_input++;
        }
    }

    /* Where finished free the memory */
    free(cpy_input); /* Crash here */

    return 0;
}

我通过声明另一个指针并分配地址来解决问题,所以它指向第一个字符,然后我释放它。它工作正常,即

  char *mem_input = cpy_input;
  free(mem_input);

我的问题是为什么我需要声明另一个指针才能释放内存?还有另一种方法吗?

非常感谢,

6 个答案:

答案 0 :(得分:4)

您需要保存原始指针。释放内存时,只能使用原始指针。您可以创建另一个变量来保存原始指针。

或者将循环放在一个单独的函数中。默认情况下,变量按值传递,即复制,当您更改函数中的指针时,只更改指针的副本。

除此之外,你的循环似乎有点奇怪。您使用从零开始的索引循环到字符串的长度,因此您可以轻松地使用该索引而不是修改指针。要么是这样,要么将循环改为while (*cpy_input != '\0')之类的东西。我从未见过这两种变体混合在一起。

顺便说一下,你的代码中有一个错误。如果当前字符是数字,则只增加指针。但是如果第一个字符是而不是一个数字,那么循环将循环直到它到达字符串的末尾,但指针将增加,你将检查第一个角色一遍又一遍。如果您只想从字符串中获取前导数字(如果有的话),可以使用循环,例如

for (; isdigit(*cpy_input); cpy_input++)
{
    /* do something, using `*cpy_input` */
}

当然

for (int i = 0; i < strlen(cpy_input); i++)
{
    /* do something, using `cpy_input[i]` */
}

答案 1 :(得分:2)

char *cpy_input = calloc(strlen(input) + 1, sizeof(char));

我们说cpu_input0x1000。应该在free()中释放Point是相同的指针。

根据您的逻辑,如果输入长度为5,则for循环cpy_input之后指向0x1005位置。如果你调用free(cpy_input)它是free(0x1005),这是免费的无效指针,它会崩溃。

答案 2 :(得分:1)

你可以改变你的循环

for(i = 0; i < strlen(cpy_input); i++) {
    if(isdigit(cpy_input[i])) {
    /* Do something here */

    }

}

或指针算术以便稍后获得初始值

答案 3 :(得分:1)

当然,还有另一种方法可以做到这一点:只需将cpy_input指针递减一次,就像递增它一样多。或者从最终cpy_input值中减去字符串的长度(假设您保存了它)。这样,您将恢复原始cpy_input值并正确释放内存。

这里的底线很简单:您必须向free传递从calloc收到的相同指针值。没有办法绕过它。因此,以这种或那种方式,您必须能够获得原始指针值。将其保存在另一个指针中实际上是您遇到的最佳解决方案。但如果你知道如何以其他方式做到这一点 - 继续使用你最喜欢的任何东西。

答案 4 :(得分:1)

calloc返回指向内存请求的内存块的指针。因此,您只能释放从calloc返回的相同指针位置。

释放原始指针或此免费备份副本。

答案 5 :(得分:1)

重要的是要理解,指针只是一个内存地址。

freecalloc后面的资源管理系统将保留一些与内存块相关联的簿记数据,特别是您通过调用calloc请求的块大小。这可能在某个查找容器中,它存储它与calloc返回的指针(即cpu_input的初始值)相关,或者此信息存储在块的正前方的内存中,据我所知,更常见。

如果您现在将cpu_input中更改的值传递给free,它将无法在其查找容器中找到簿记数据,或者它将在指针前面查找book keepin数据,它将在找到你的数据字符串,这可能完全没有意义。

因此,保留原始指针副本的解决方案是合适的。