昨天我问过一个类似的question关于如何free
为sub-string
分配内存的问题。现在我还有一个关于同一问题的问题(涉及一系列条件),如何在不进行双重释放的情况下释放以下子字符串?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct st_ex {
char product[16];
float price;
};
struct st_temp {
char *prod;
};
char *temp = NULL;
// from stackoverflow
char* substr( const char* source, size_t start, size_t end )
{
char* dest = malloc( end - start + 1) ;
memcpy( dest, &source[start], end - start ) ;
dest[end - start] = 0 ;
return dest ;
}
int main()
{
struct st_ex structs[] = {{"mp3 player", 2.0f}, {"plasma tv", 20.0f},
{"notebook", 10.0f}, {"smartphone", 49.9f},
{"dvd player", 10.0f}, {"matches", 0.2f }};
struct st_temp **temp_struct;
size_t j, i;
temp_struct = malloc(sizeof *temp_struct * 6);
for (j = 0; j < 6; j++)
temp_struct[j] = malloc(sizeof *temp_struct[j]);
size_t structs_len = sizeof(structs) / sizeof(struct st_ex);
// NOTE: that structs_len may vary in size - not just 6
for(i=0; i<structs_len; i++){
if (i == 0)
temp_struct[i]->prod = "+";
else if(i == 1)
temp_struct[i]->prod = "Bar";
else if(i == 5)
temp_struct[i]->prod = "Foo";
else {
temp = substr(structs[i].product, 0, 4);
temp_struct[i]->prod = temp;
}
}
for(i=0; i<6; i++ )
printf("%s\n",temp_struct[i]->prod);
for(i = 0; i < 6; i++ ){
/* can I do something like this? */
/*if (i != 0 || i != 1 || i != 5)*/
free(temp_struct[i]->prod);
free(temp_struct[i]);
}
free(temp_struct);
return 0;
}
答案 0 :(得分:1)
问题在于,有时您会将temp_struct[i]->prod
设置为引用的字符串(“条形码”),您无法释放它,有时也会将其设置为您必须释放的子视图调用的结果。
最简单的解决方案是始终将其设置为必须释放的字符串。
temp_struct[i]->prod = new_string("Bar");
,其中
char* new_string( const char* source )
{
char* dest = malloc( strlen(source) + 1 ) ;
strcpy(dest, source);
return dest ;
}
或者,如果您需要免费
,您必须跟踪 struct st_temp {
char *prod;
int prod_must_be_freed;
};
将prod_must_be_freed设置为0或1并在释放之前检查它。
最后,通过使用函数来操作这些结构而不是直接使用它们来改善整个过程。然后你可以创建一个free_st_temp(st_temp*)
来检查是否应该释放prod,然后释放结构。你的循环将是
for(i = 0; i < 6; i++ ){
free_st_temp(temp_struct[i]);
}
答案 1 :(得分:0)
是的,虽然您希望取消注释if
,并更改if
与&&
而不是||
相关联的条件(否则它将始终是真的 - 每个数字不等于零或不等于一个!)
存储在temp_struct[i]->prod
中i
除了0,1和5之外的子字符串在substr
函数内分配malloc
,因此您可以而且应该取消分配他们与free
。
同样,每个temp_struct
元素都分配了malloc
,因此可以并且应该使用free
取消分配。
我不确定你认为双免费会来自哪里。您是否在考虑在调用free(tmp_struct[i])
时tmp_struct[i]->prod
指向的内存也将被释放?情况并非如此。当你释放指向包含指针的结构的指针时,结构指针本身的内存被释放(因为它是结构的一部分),但那些指针指向的内存不是,并且必须单独解除分配(因为它在结构外部)。除了if
条件中的错误之外,你编写它的方式是正确的方法。
答案 2 :(得分:0)
子字符串不会占用额外的内存。它们是指向现有字符串部分的指针。
答案 3 :(得分:0)
是的,假设您的substr
正在为malloc
分配子字符串的内存,那么当您完成内存时,free
内存是合理的(必要的)。也就是说,我认为你现在正在做的事情是非常脆弱和容易出错的(温和地说)。如果您有任何选择,我会以相同的方式为所有 prod
成员分配字符串 - 如果您不能静态分配它们,那么动态分配它们,所以当你释放结构时,你可以统一地这样做。当且仅当动态分配时,试图确保您将下标与免费prod
匹配,这实际上是在乞求麻烦。
答案 4 :(得分:0)
您还有其他问题。当你执行temp_struct[i]->prod = "Bar";
时你正在为prod分配一个const char *。该指针无法释放(最可能的结果是崩溃)。因此,如果您希望以这种方式设置代码,使得prod可以指向您从malloc获得的动态内存或指向常量字符串文字,您还需要跟踪它是哪一个并且只释放动态内存
评论中的条件在技术上会起作用,但形式会非常糟糕。最好的想法是不要在同一个指针中混合和匹配字符串类型。但是如果你坚持这样做,那么改进就是在你的结构中添加另一个变量,当需要释放prod时设置为true,否则为false。