在C中的宏内有条件地释放已分配的内存

时间:2013-05-03 19:48:54

标签: c memory-management macros

我有一个函数读取csv文件,然后使用它的参数更新struct。 我希望能够遍历一个结构元素,所以我转向了宏。解析csv文件的输出是文件行和列的二维字符串数组。要将字符串转换为各自的数据类型(目前结构只有intchar*),我在宏中使用了转换宏来循环遍历结构。

CVT_INT atoi(str)
CVT_STR str

但是,当解决通过解析csv文件而释放分配的内存时,如果在文件中字符串未在开头或结尾分组在一起,则会变得棘手。

csv[row][col]
string|string|int|string|int
string|string|int|string|int
...

for(int row = 0; row < number_of_rows; row++)
    for(int col = 2; col < number_of_cols; col++)
        free(csv[row][col]) // frees string when row[i][3]

我可以确保所有字符串都在结构的开头,但我希望它是动态的,我不想考虑确保数据类型是分组的。

我可以释放由CVT_INT转换的已分配字符串,但释放CVT_STR使用的字符串将导致释放struct的字符串。我能想到一个解决方法: 1.分配新的空间 2.复制旧字符串 3.释放旧字符串。

CVT_STR strcpy((char*)malloc(sizeof(char)*(1+strlen(str))), str)

然而,在实现上述内容时,无论何时调用它都会导致崩溃,我不明白为什么。任何人都可以给我一个解释和解决方法/一个做同样工作的不同路线吗?我知道它效率不高,所以也欢迎提出改善这方面的建议。

另一种可能性,我只能免费int。但是,我无法弄清楚如何在宏中执行此操作,因为它必须返回一个int。

下面是我调用包含转换宏的循环结构宏的示例。

#define STRUCT(type, name, converter) \
        obj->struct.name = converter(csv[row][col++]);
STRUCT_FIELDS
#undef PLAYER

感谢您的帮助

更新:

更换

CVT_STR strcpy((char*)malloc(sizeof(char)*(1+strlen(str))), str)

CVT_STR strdup(str)

工作,但我不明白为什么。也许有人可以启发我?

2 个答案:

答案 0 :(得分:2)

您需要向strlen添加一个不包含尾随NUL字节的内容。

CVT_STR strcpy((char*)malloc((sizeof(char) * strlen(str)) + 1), str)

或只是

CVT_STR strcpy((char*)malloc(strlen(str) + 1), str)

答案 1 :(得分:1)

所以,我们有一个转换东西的宏:

#define STRUCT(type, name, converter) \
    obj->type.name = converter(csv[row][col++]);    // Guessing `struct` meant `type`?

用这样的东西调用它:

STRUCT(foo, bar, CVT_STR)

现在,如果CVT_STR是一个宏,宏会直接扩展到STRUCT宏扩展中,如下所示:

obj->foo.bar = strdup(csv[row][col++]); 

现在,如果您想要逐步完成此操作,那么您将遇到困难,因为它只是将宏作为一步。

如果相反,我们写一个函数:

inline char *cvt_str(const char *str)
{
    char *tmp = strdup(str); 
    return tmp;
}

并使用此功能:

STRUCT(foo, bar, cvt_str)

现在我们可以使用调试器在cvt_str中设置一个断点,并逐步查看它以查看它出错的地方。