简体   繁体   English

在C中拆分字符串时出现内存泄漏问题

[英]Memory leak problems while splitting a string in C

Im trying to split a string according to the following rules: 我试图根据以下规则拆分字符串:

  1. words without "" around them should be treated as seperate strings 周围没有“”的单词应视为单独的字符串
  2. anything wiht "" around it should be treated as one string 周围带有“”的任何内容都应视为一个字符串

However when i run it in valgrind i get invalid frees and invalid read size errors, but if i remove the two frees i get a memory leak. 但是,当我在valgrind中运行它时,我得到了无效的释放和无效的读取大小错误,但是如果我删除了两个释放,则会出现内存泄漏。 If anyone could point me in the right direction i would appreciate it 如果有人能指出我正确的方向,我将不胜感激

The code that calls split_string 调用split_string的代码

    char *param[5];
    for(i = 0;i < 5;i++) {
            param[i] = NULL;
    }
    char* user = getenv("LOGNAME");
    char tid[9];
    char* instring = (char*) malloc(201);

    /
    while((printf("%s %s >",user,gettime(tid)))&&(instring
            =fgets(instring,201,stdin)) != NULL) {
            int paramsize = split_string(param, instring);

The code that tries to free param 试图释放参数的代码

                for(i = 0;i < 5;i++) {
                if(param[i] != NULL) {
                    free(param[i]);
                    fprintf(stderr,"%d",i);
                }
            }

    int split_string(char** param, char* string) {
    int paramplace = 0; //hvor vi er i param
    int tempplace = 0; //hvor i temp vi er

    char* temp = malloc(201); 
    int command = 0; 
    int message = 0; 
    for(; (*string != '\0') && (*string != 10) && paramplace < 4; string++) {
            if((*string == ' ') && (message == 0)) {
                    if(command == 1) {
                        temp[tempplace] = '\0'; 
                        param[paramplace++] = temp; 
                        tempplace = 0;
                        command = 0;
                    }
            }
            else {
                    if(*string =='"') {
                            if(message == 0) message = 1;
                            else message = 0;
                    }
                    if(command == 0) {
                            free(temp);
                            temp = malloc(201);
                    }
                    command = 1;
                    if(*string != '"') {
                            temp[tempplace++] = *string;
                    }
            }
    }
    if(command == 1) {
            temp[tempplace] = '\0';
            param[paramplace++] = temp;
    }
    param[paramplace] = NULL;
    free(temp);
    return paramplace;
}

As far as I can see, you want to put the split strings into param as an array of pointers (presumably making the caller responsible for freeing them). 据我所知,您希望将拆分后的字符串作为一个指针数组放入param中(大概让调用者负责释放它们)。 In the first branch of the if statement in your loop, you do so by assigning the current temp buffer to that place. 在循环中if语句的第一个分支中,您可以通过将当前temp缓冲区分配到该位置来实现。 However, once you start a new string (when comnmand == 0 , you free that space, rendering the previous param entry pointer invalid. 但是,一旦开始一个新字符串(当comnmand == 0 ,您就释放了该空间,从而使先前的param条目指针无效。

Only free each pointer once. 每个指针只能释放一次。 I wouldn't rule out other leaks in this code: I think you can simplify your state machine (and probably find other bugs as a result). 我不会排除此代码中的其他泄漏:我认为您可以简化状态机(结果可能会发现其他错误)。

When you free the temp buffer you also free the param[] buffer, where your tokens are stored. 释放临时缓冲区时,还释放存储令牌的param []缓冲区。 On the other hand, if you don't call free(temp) , which you shouldn't, it will be the responsibility of the caller of your function to call free(param[n]) , when the tokens aren't needed. 另一方面,如果您不调用free(temp)而不应该调用,则在不需要令牌时,函数调用者有责任调用free(param[n]) 。 。

Maybe you're not removing the right free()'s? 也许您没有删除正确的free()? The actual problem might be in the code that calls split_string. 实际的问题可能出在调用split_string的代码中。 Can you show it? 你能证明吗?

It's hard to understand your code. 很难理解您的代码。 I suggest you use sscanf instead. 我建议您改用sscanf。

You can use a format string like this: 您可以使用如下格式的字符串:

"\"%[^\"]\"%n"

Read up on what it does. 阅读它的功能。

I wrote an example: 我写了一个例子:

if( sscanf( string, "\"%[^\"]\"%n", matchedstring, &bytesread ) )
{
    handlestring( matchedstring );
    string += bytesread;
}
else if( sscanf( string, "%s%n", matchedstring, &bytesread ) )
{
    handlestring( matchedstring );
    string += bytesread;
}
else
{
    handleexception();
}

Untested. 未经测试。 :) :)

Thanks to all the comments i found the answer. 感谢所有评论,我找到了答案。 The problem was that the first malloc before the for loop is superfluous as there will be another one before it starts to put temp into param and therefore there were no pointers to the first malloc so it was simply lost. 问题在于for循环之前的第一个malloc是多余的,因为在将temp放入参数之前会有另一个,因此没有指向第一个malloc的指针,因此它完全丢失了。

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

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