简体   繁体   English

释放函数中分配的C **指针时出错

[英]Error freeing C** pointer malloced in function

The program runs fine except for the last free, which results in the program freezing. 该程序运行良好,但最后一个可用程序除外,这导致程序冻结。 When I comment out the last 'free' it runs fine. 当我注释掉最后一个“免费”时,它运行正常。

The program gets all substrings from a string and returns it. 该程序从字符串中获取所有子字符串并返回它。

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

char** getPrefixes(char* invoer);

int main()
{
    char buffer[100];
    char *input;
    char **prefixes;
    int counter = 0;

    puts("Give string.");
    fgets(buffer, 99, stdin);
    fflush(stdin);

    if (buffer[strlen(buffer) - 1] == '\n')
        buffer[strlen(buffer) - 1] = '\0';

    input= (char*)malloc(strlen(buffer) + 1);

    if (input == NULL)
    {
        puts("Error allocating memory.");
        return;
    }

    strcpy(input, buffer);

    prefixes = (char**) getPrefixes(input);

    for (counter = strlen(input); counter > 0;  counter--)
    {
        puts(prefixes[counter]);
        free(prefixes[counter]);
    }

    free(input);

    free(prefixes);
}

char** getPrefixes(char* input)
{
    char** prefixes;
    int counter;

    prefixes = malloc(strlen(input) * sizeof(char*));

    if (prefixes == NULL)
    {
        puts("ELM.");
        return NULL;
    }


    for (counter= strlen(input); counter> 0; counter--)
    {
        prefixes[counter] = (char*)malloc(counter + 1);
        strcpy(prefixes[counter], input);
        input++;
    }

    return prefixes;
}

Thanks in advance! 提前致谢!

allocating memory for pointer to pointer: 为指针分配内存:

char** cArray = (char**)malloc(N*sizeof(char*));

for(i=0;i<N;i++)
    cArray[i] = (char*)malloc(M*sizeof(char));

De-allocating memory - in reverse order: 取消分配内存-反向:

for(i=0;i<N;i++)
    free(cArray[i]);
free(cArray)

I hope this gives you a little insight on what's wrong. 我希望这可以使您对什么地方出了点问题。

you are calling strcpy with prefixes[counter] as destination. 您正在调用带有前缀[counter]作为目标的strcpy。 However, you've only allocated 4/8 bytes per prefixes[counter] depending on the size of (char*) 但是,根据(char *)的大小,每个前缀[counter]只分配了4/8个字节

When you call strcpy you're copying all of input all the way to the end requiring strlen(input)! 当您调用strcpy时,您将所有输入复制到需要strlen(input)的最后! space 空间

Doing this will corrupt the heap which might explain why the program is freezing. 这样做会破坏堆,这可能解释了程序冻结的原因。

The reason for your program freezing is simple: undefined behaviour + invalid return values: _Your main function returns void , not an int : add return 0 ASAP! 程序冻结的原因很简单:不确定的行为+无效的返回值:_您的主函数返回void ,而不是int :尽快添加return 0 If you type in echo $? 如果输入echo $? in your console after executing your compiled binary, you should see a number other than 0 . 在执行编译后的二进制文件后,在控制台中,您应该看到除0以外的数字。 This is the program's exit code. 这是程序的退出代码。 anything other than 0 means trouble. 0以外的任何东西都意味着麻烦。 if the main did not return an int, it's bad news. 如果main没有返回int,则是个坏消息。

Next: 下一个:
The undefined behaviour occurs in a couple of places, for example right here: 未定义的行为发生在几个地方,例如在这里:

prefixes = malloc(strlen(input) * sizeof(char*));
//allocate strlen(input) pointers, if input is 10 long => valid indexes == 0-9
for (counter= strlen(input); counter> 0; teller--)
{//teller doesn't exist, so I assume you meant "counter--"
    prefixes[teller] = (char*)malloc(counter + 1);//first call prefixes[10] ==> out of bounds
    strcpy(prefixes[counter], input);//risky, no zero-termination... use calloc + strncpy
    input++;
}

Then, when free-ing the memory, you're not freeing the pointer @ offset 0, so the free(prefixes) call is invalid: 然后,释放内存时,您不会释放偏移量为@ 0的指针,因此free(prefixes)调用无效:

for (counter = strlen(input); counter > 0;  counter--)
{//again 10 --> valid offsets are 9 -> 0
    puts(prefixes[counter]);
    free(prefixes[counter]);
}
free(prefixes);//wrong

Again, valid indexes are 0 and up, your condition in the loop ( counter > 0 ) means that the loop breaks whenever counter is 0. You, at no point, are freeing the first pointer in the array, the one at index/offstet 0. 同样,有效索引为0或更高,循环中的条件( counter > 0 )意味着只要counter为0,循环就会中断。您在任何时候都不会释放数组中的第一个指针,即index / offstet处的指针。 0。

Write your loops like everyone would: 像每个人一样编写循环:

for (int i=0, size_t len = strlen(input); i<len; ++i)
{
    printf("%d\n", i);//prints 0-9... 10 lines, all valid indexes
}

Change your loops, and make sure you're only using the valid offsets and you _should be good to go. 更改循环,并确保仅使用有效的偏移量,并且_应该很好。 using strncpy , you can still get the same result as before: 使用strncpy ,您仍然可以获得与以前相同的结果:

for (int i=0;i<len;++i)
{
    //or malloc(i+2), char is guaranteed to be 1
    //I tend to use `calloc` to set all chars to 0 already, and ensure zero-termination
    prefixes[i] = malloc((i+2)*sizeof(*prefixes[i]));
    strncpy(prefixes[i], input, i+1);//max 1 - 10 chars are copied
}

If we apply this to your code, and re-write it like so: 如果我们将其应用于您的代码,然后像这样重写它:

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

char** getPrefixes(char* input);

int main( void )
{
    char *input;
    char **prefixes;
    int counter, i;

    input= calloc(50,1);
    if (input == NULL)
    {
        puts("Error allocating memory.");
        return;
    }
    strcpy(input, "teststring");

    prefixes = getPrefixes(input);
    counter = strlen(input);
    for (i=0; i<counter;++i)
    {
        puts(prefixes[i]);
        free(prefixes[i]);
    }

    free(input);
    free(prefixes);
    return 0;
}

char** getPrefixes(char* input)
{
    int i, counter = strlen(input);
    char** prefixes = malloc(counter * sizeof *prefixes);

    if (prefixes == NULL)
    {
        puts("ELM.");
        return NULL;
    }

    for (i=0; i<counter; ++i)
    {
        prefixes[i] = calloc(i + 2,sizeof *prefixes[i]);
        strncpy(prefixes[i], input, i+1);
    }
    return prefixes;
}

The output we get is: 我们得到的输出是:

t
te
tes
test
tests
testst
teststr
teststri
teststrin
teststring

As you can see for yourself 如您所见

on this codepad 在此键盘上

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM