我可以释放指针,例如:
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);
}
答案 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()
的实现只是在该地址之前读取内存以确定要回收多少内存。如果你提供一些其他地址,那么它无法知道这是在分配的中间,它需要扫描回到开头才能找到信息。
更复杂的设计会保留所有分配的列表,然后确定地址指向哪一个。但是这会占用更多的内存并且效率会低得多,因为它必须搜索包含的分配。