在更改其值后释放C指针

时间:2018-03-30 03:38:41

标签: c pointers memory-leaks

我可以释放指针,例如:

unsigned char *string1=NULL;
string1=malloc(4096);

改变其价值后如:

*string1+=2;

free(string1)可以在递增后释放相应的内存块(例如指向字符串的一部分),或者我是否需要保留原始指针值以便释放?

例如,对于C语言中Visual Basic 6函数LTrim的实现,我需要传递**字符串作为参数,但最后我将返回*string+=string_offset_pointer以超出任何空格/制表符

我认为我在这里改变指针所以如果我这样做,我需要保留原始指针的副本以释放它。最好将非空白内容覆盖到字符串本身,然后用0终止它,以避免需要额外的指针副本来释放内存:

void LTrim(unsigned char **string)
{
 unsigned long string_length;
 unsigned long string_offset_pointer=0;


 if(*string==NULL)return;

 string_length=strlen(*string);
 if(string_length==0)return;


 while(string_offset_pointer<string_length)
 {
  if(
     *(*string+string_offset_pointer)!=' ' &&
     *(*string+string_offset_pointer)!='\t'
    )
  {
   break;
  }

  string_offset_pointer++;
 }


 *string+=string_offset_pointer;
}

最好让函数用它的子字符串覆盖字符串但不改变指针的实际值,以避免需要它的两个副本:

void LTrim(unsigned char **string)
{
 unsigned long string_length;
 unsigned long string_offset_pointer=0;
 unsigned long string_offset_rebase=0;


 if(*string==NULL)return;

 string_length=strlen(*string);
 if(string_length==0)return;


 //Detect the first leftmost non-blank
 //character:
 ///
  while(string_offset_pointer<string_length)
  {
   if(
      *(*string+string_offset_pointer)!=' ' &&
      *(*string+string_offset_pointer)!='\t'
     )
   {
    break;
   }

   string_offset_pointer++;
  }



 //Copy the non-blank spaces over the
 //originally blank spaces at the beginning
 //of the string, from the first non-blank
 //character up to the string length:
 ///
  while(string_offset_pointer<string_length)
  {
   *(*string+string_offset_rebase)=
   *(*string+string_offset_pointer);

   string_offset_rebase++;
   string_offset_pointer++;
  }



 //Terminate the newly-copied substring
 //with a null byte for an ASCIIZ string.
 //If the string was fully blank we will
 //just get an empty string:
 ///
  *(*string+string_offset_rebase)=0;


 //Free the now unused part of the
 //string. It assumes that realloc()
 //will keep the current contents of our
 //memory buffers and will just truncate them,
 //like in this case where we are requesting
 //to shrink the buffer:
 ///
  realloc(*string,strlen(*string)+1);
}

2 个答案:

答案 0 :(得分:7)

因为你实际上在做

unsigned char *string1=NULL;
string1=malloc(4096);
*string1+=2;
free(string1);

free(string1)正在传递malloc()来电的结果。

如果*string1 += 2未初始化,free()将会发生未定义的行为,无论string1[0]的调用如何。 (即如果有一些操作在上面的第二行和第三行之间初始化string1[0],那么行为就完全明确了。)

如果从*string1 += 2删除星号以形成语句string1 += 2,则free()的调用将具有未定义的行为。 free()必须传递malloc()(或calloc()realloc())返回的尚未解除分配的值。

答案 1 :(得分:6)

传递给free()的值必须是malloc()calloc()realloc()返回的指针。任何其他值都会导致未定义的行为。

因此,如果修改它,则必须保存原始指针。在您的代码中,您实际上并未修改指针,只需增加其指向的位置的内容,这样您就不会遇到此问题。

为什么用这种方式指定语言,你可能会问?它允许非常有效的实现。常见的设计是将大小分配存储在数据之前的存储器位置中。因此free()的实现只是在该地址之前读取内存以确定要回收多少内存。如果你提供一些其他地址,那么它无法知道这是在分配的中间,它需要扫描回到开头才能找到信息。

更复杂的设计会保留所有分配的列表,然后确定地址指向哪一个。但是这会占用更多的内存并且效率会低得多,因为它必须搜索包含的分配。