字符串修剪导致内存泄漏?

Com*_*riS 1 c string memory-leaks trim

我很好奇修剪字符串的正确方法是确保不会发生内存泄漏.我想这可能真的是一个基于free()工作原理的问题.我已经包含了trim()函数的代码.见下文.

int main()
{
    char* testStr1 = strdup("some string");
    char* testStr2 = strdup("   some string");
    char* testStr3 = strdup("some string     ");

    trim(&testStr1);
    trim(&testStr2);
    trim(&testStr3);

    free(testStr1); // no memory leak
    free(testStr2); // possible memory leak?
    free(testStr3); // possible memory leak?

    return 0;
}

int trim(char** pStr)
{
 if(pStr == NULL || *pStr == NULL)
  return FAILURE;
 char* str = *pStr;
 while(isspace(*str)) {
  (*pStr)++;
  str++;
 }

 if(*str == 0) {
  *pStr = str;
  return SUCCESS;
 }

 char *end = str + strlen(str) - 1;
 while(end > str && isspace(*end))
  end--;
 *(end+1) = 0;

 *pStr = str;
 return SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

Jer*_*fin 14

您传递给的指针free需要与从(或或)接收的指针完全相同,而不仅仅是指向返回的内存区域的指针.因此,您的第二个字符串是导致问题的字符串.你的第一个和第三个都很好,因为你传递的指针与你收到的指针(通过)匹配.malloccallocreallocmallocfreemallocstrdup

但是,在这种情况下你得到的并不是内存泄漏 - 它是未定义的行为.


Mat*_*hen 5

是的,这会导致内存泄漏,但更糟糕的是,它会导致未定义的行为.由于trim修改了指针变量,因此main将指针传递给free未返回的指针malloc.这是未定义的行为,它会在许多实现上破坏堆.

至少有三种正确的方法可以解决这个问题.

1.修剪分配并返回一个新字符串,并让调用者负责释放新字符串以及旧字符串(如果需要):

char *trim(char *orig);
// ...
char *trimmed1 = trim(testStr1);
free(testStr1);
// ...
free(trimmed1);
Run Code Online (Sandbox Code Playgroud)

2.让调用者分配一个相同长度的新字符串(保守),然后传入两个指针.

int trim(char *orig, char *new);
// ...
char *trimmed1 = malloc(strlen(testStr1) + 1);
trim(testStr1, trimmed1);
free(testStr1);
// ...
free(trimmed1);
Run Code Online (Sandbox Code Playgroud)

3.将琴弦修剪到位,向左移动:

| | |t|r|im| | |\0|->
|t|r|i|m|\0|

int *trim(char *orig);
trim(testStr1);
// ...
free(testStr1);
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,`memmove()`对于实现选项#3非常有用. (2认同)