【发布时间】:2013-04-28 07:18:12
【问题描述】:
我有一个函数可以读取一个 csv 文件,然后用它的参数更新一个 struct。
我希望能够循环遍历结构元素,所以我转向宏。解析 csv 文件的输出是文件行和列的二维字符串数组。为了将字符串转换为它们各自的数据类型(当前结构只有int 和char*),我在用于循环遍历结构的宏中使用了一个转换宏。
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 使用的字符串会导致结构的字符串被释放。我可以想到一种解决方法: 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)
工作,但我不明白为什么。也许有人可以启发我?
【问题讨论】:
-
你为什么要使用宏,而不是内联函数[至少在最后一步,你仍然可以使用宏来做转换器的扩展,但传递一个函数而不是宏作为“转换器”。这样,您就可以调试代码(而且很可能不会降低效率,因为编译器会内联函数!)
-
您的系统是否缺少
strdup()? -
@user315052:由于对现有答案的评论说 strcpy() 不起作用,我怀疑一个函数做同样的事情[或者你认为
strdup做与strcpy(malloc(strlen(str)+1), str)不同的东西 - 当然,它会检查 malloc 是否为空,等等,但除此之外它是相同的。 -
谢谢user315052,我以前没见过这个功能,它已经解决了这个问题!从阅读手册页来看,它似乎与我用
strcpy硬编码的方式完全相同,但由于某种原因,它在我的代码没有的地方工作。也许宏不喜欢malloc的类型转换。内联函数 - 我不熟悉它们,但建议我使用宏来循环浏览struct。我猜测使用宏来执行此操作表明我不能使用内联函数?不过,我会对此进行研究,因为缺乏调试功能已经令人沮丧。 -
我猜你没有
#include <stdlib.h>,所以你的演员隐藏了丢失的原型。由于缺少原型,并且如果int小于指针,您的malloc()s 返回值将被截断,从而导致指针无效。
标签: c memory-management macros