我正在为一个C++库编写一个包装器,该库需要与普通C一起使用。该库有一个名为checkError()
的函数。此函数引发与对象内发生的错误相关的异常。在C++包装器中,我捕获了这个错误,对一个C兼容的结构进行mallocated,将错误消息和信息分配给错误结构变量,然后我将指向该结构的指针传回。这一切都很好,但我担心一旦C调用函数处理完结构,内存就会泄漏。
对于这个问题,让我们假设库的对象被称为objectA
,库被称为libraryA
C&C++兼容wrapper.h
:
#ifndef LIBRARY_WRAPPER_DEFINITION
#define LIBRARY_WRAPPER_DEFINITION
#ifdef __cplusplus
extern "C" {
#endif
typedef struct wrapper_error_message_struct{
char *what;
char *typeAsText;
unsigned char severityLevel; /* 0-10; 0 = lowest severity. 10 = highest severity */
} wrapper_error_message_t;
typedef void *pLibObj_t;
/**
* I've omitted the other prototypes, typedefs, etc.
**/
/* checkError()'s wrapper prototype */
wrapper_error_message_t *wrapper_check_error(pLibObj_t ptrObjectToCheck);
#ifdef __cplusplus
}
#endif
#endif
wrapper.cpp
:中wrapper_check_error
的C++实现
/* Imports and other functions preceding wrapper_check_error() */
wrapper_error_message_t *wrapper_check_error(pLibObj_t ptrObjectToCheck){
/* for the sake of this question, I've omitted the validity checks on
* ptrObjectToCheck. I've also omitted my malloc checks. */
libraryA::objectA *convertedObj = (libraryA::objectA *)ptrObjectToCheck;
size_t structSize = sizeof(wrapper_error_message_t);
size_t charSize = sizeof(char); // just in case it's not 1 on this system.
try{
convertedObj->checkError();
/* if the checkError() function did not throw an error, then we
can simply return NULL indicating that no ERROR was thrown */
return NULL;
}catch(libraryA::SomeLibraryExceptionType_1 &err){
wrapper_error_message_t *cErr = (wrapper_error_message_t *)malloc(structSize);
cErr->severityLevel = 3;
const char *errWhat = err.what();
cErr->what = (char *)malloc((strlen(errWhat)+1) * charSize);
strcpy(cErr->what, errWhat);
const char errorType[] = "Library Exception Type Name 1";
cErr->typeAsText = (char *)malloc((strlen(errorType)+1) * charSize);
strcpy(cErr->typeAsText, errorType);
return cErr;
}catch(libraryA::SomeLibraryExceptionType_2 &err){
/* Roughly the same as SomeLibraryExceptionType_1's catch statement */
}catch(libraryA::SomeLibraryExceptionType_3 &err){
/* Roughly the same as SomeLibraryExceptionType_1's catch statement */
}catch(std::exception &err)
wrapper_error_message_t *cErr = (wrapper_error_message_t *)malloc(structSize);
cErr->severityLevel = 7;
const char *errWhat = err.what();
cErr->what = (char *)malloc((strlen(errWhat)+1) * charSize);
strcpy(cErr->what, errWhat);
const char errorType[] = "Unknown standard exception (std::exception)";
cErr->typeAsText = (char *)malloc((strlen(errorType)+1) * charSize);
strcpy(cErr->typeAsText, errorType);
return cErr;
}catch(...){
wrapper_error_message_t *cErr = (wrapper_error_message_t *)malloc(structSize);
cErr->severityLevel = 10;
cErr->what = NULL;
const char errorType[] = "Unknown. Could not be caught.";
cErr->typeAsText = (char *)malloc((strlen(errorType)+1) * charSize);
strcpy(cErr->typeAsText, errorType);
return cErr;
}
}
在main.c
:中使用wrapper_check_error()
的普通C函数
/* imports, irrelevant functions, irrelevant variable definitions */
void someFunction(){
pLibObj_t ourWrappedObj;
/*
* function code before error check.
*/
wrapper_error_message_t *errorMsg = wrapper_check_error(ourWrappedObj);
if(wrapper_error_message_t != NULL){
/* there was an error.
* the code within this if statement:
* - processes the error message
* - logs information about it (current time, type, severity and the what message)
* - makes logical decisions about how to handle it if possible.
*/
free(errorMsg);
errorMsg = NULL;
/* In the line above, the function frees the malloc'd structure to remove it
* from the heap.
*
* This free statement is what I'm concerned about.
*
*/
}
// etc.
}
free(errorMsg)
是否也会释放char *what
和char *typeAsText
,因为它们是正在被释放的结构的成员?根据我所做的一些阅读,我目前相信what
和typeAsText
所指向的值仍将存在于堆中,因为errorMsg
只包含指向这些值的指针,而不是值本身。
如果*what
和*typeAsText
仍在堆中,我将编写一个函数,在释放结构本身之前释放结构的成员。不过,我只想在必要的时候这样做。
如果有人能对此提供一些指导/见解,我们将不胜感激。
谢谢。
如果这个问题重复,我提前道歉。如果是,请给我指出类似问题的方向,这样我就可以阅读那里的答案。我在SO和其他网站上搜索过,但没有找到任何能回答我问题的东西。
我从我的项目中摘录了一些代码,缩短了代码,并重命名了变量/函数。除了一些错误检查之外,如果代码中有我没有注意到的明显错误,请发表评论,以便我可以修改。如果有什么不清楚的地方,请在评论中告诉我,我会尽最大努力更新问题并澄清。
由于有三个malloc()
调用用于构建将所有权传递给的对象:
wrapper_error_message_t *cErr = (wrapper_error_message_t *)malloc(structSize);
cErr->severityLevel = 3;
const char *errWhat = err.what();
cErr->what = (char *)malloc((strlen(errWhat)+1) * charSize);
strcpy(cErr->what, errWhat);
const char errorType[] = "Library Exception Type Name 1";
cErr->typeAsText = (char *)malloc((strlen(errorType)+1) * charSize);
strcpy(cErr->typeAsText, errorType);
return cErr;
需要3次呼叫free()
:
free(errorMsg->typeAsText);
free(errorMsg->what);
free(errorMsg);
顺便说一句,sizeof(char)
的定义是1,所以没有必要为此做任何特殊的事情。
另一方面,我建议使用strdup()
,而不是像这样容易出错的杂波
cErr->what = (char *)malloc((strlen(errWhat)+1) * charSize);
strcpy(cErr->what, errWhat);