附加到字符串时C中的内存泄漏

附加到字符串时C中的内存泄漏,c,memory-leaks,c-strings,C,Memory Leaks,C Strings,Valgrind说有内存泄漏,但我不知道是什么。我尝试在append函数中放入free,释放main末尾的字符串,但它仍然抱怨 #包括 #包括 #包括 空附加(字符*字符串,字符c) { int stringlength=strlen(字符串); char*tmp=realloc(string,sizeof(char)*(stringlength+sizeof(char)+sizeof(char)); if(tmp==NULL) { 免费(tmp); 自由(弦); printf(“追加字符时出错

Valgrind说有内存泄漏,但我不知道是什么。我尝试在append函数中放入free,释放main末尾的字符串,但它仍然抱怨

#包括
#包括
#包括
空附加(字符*字符串,字符c)
{
int stringlength=strlen(字符串);
char*tmp=realloc(string,sizeof(char)*(stringlength+sizeof(char)+sizeof(char));
if(tmp==NULL)
{
免费(tmp);
自由(弦);
printf(“追加字符时出错\n”);
出口(1);
}
字符串=tmp;
字符串[stringlength]=c;
字符串[stringlength+1]='\0';
}
int main()
{
char*string=malloc(sizeof(char));
字符串[0]='\0';
printf(“追加前的字符串:%s\n”,字符串);
追加(字符串,'c');
printf(“追加后的字符串:%s\n”,字符串);
自由(弦);
返回0;
}
以下是Valgrind的输出:
(它在Pastebin中,因此堆栈溢出实际上会让我发布这个问题

您的主要问题不是内存泄漏,而是无效访问:

无效和免费:

因为它们有未定义的行为

  • 当您执行
    char*tmp=realloc(string,sizeof(char)*(stringlength+sizeof(char)+sizeof(char));
    时,释放的字符串来自main,因此当您在main中打印它时,您可以访问一个释放的块。请注意,realloc释放了块这一事实不是强制性的

  • 因为您没有在append中释放realloc新分配的tmp,所以会造成内存泄漏

  • 然后再次释放realloc已经释放的字符串

另外
sizeof(char)*(stringlength+sizeof(char)+sizeof(char))
很奇怪,你已经改变了
sizeof(char)
的定义是1,可以是
stringlength+2

你想要的是:

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

void append(char ** string, char c)
{
   size_t stringlength = strlen(*string);

  *string = realloc(*string, stringlength + 2);

  if (*string == NULL)
  {
     fprintf(stderr, "cannot allocate memory\n");
     exit(1);
  }

  (*string)[stringlength] = c;
  (*string)[stringlength+1] = '\0';
}

int main()
{
    char* string = malloc(1);

    string[0] = '\0';

    printf("string before appending: '%s'\n", string);
    append(&string, 'c');
    printf("string after appending: '%s'\n", string);
    free(string);
    return 0;
}

无效访问和释放比内存泄漏重要得多,因为它们有未定义的行为。请参阅我的答案,了解为什么会出现所有这些问题,以及删除这些问题的建议
Invalid free() / delete / delete[] / realloc()
...
Address 0x49d0028 is 0 bytes inside a block of size 1 free'd
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void append(char ** string, char c)
{
   size_t stringlength = strlen(*string);

  *string = realloc(*string, stringlength + 2);

  if (*string == NULL)
  {
     fprintf(stderr, "cannot allocate memory\n");
     exit(1);
  }

  (*string)[stringlength] = c;
  (*string)[stringlength+1] = '\0';
}

int main()
{
    char* string = malloc(1);

    string[0] = '\0';

    printf("string before appending: '%s'\n", string);
    append(&string, 'c');
    printf("string after appending: '%s'\n", string);
    free(string);
    return 0;
}
pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra m.c
pi@raspberrypi:/tmp $ valgrind ./a.out
==17097== Memcheck, a memory error detector
==17097== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==17097== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==17097== Command: ./a.out
==17097== 
string before appending: ''
string after appending: 'c'
==17097== 
==17097== HEAP SUMMARY:
==17097==     in use at exit: 0 bytes in 0 blocks
==17097==   total heap usage: 3 allocs, 3 frees, 1,027 bytes allocated
==17097== 
==17097== All heap blocks were freed -- no leaks are possible
==17097== 
==17097== For counts of detected and suppressed errors, rerun with: -v
==17097== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)