我正在研究一个C ++库的包装器,我需要使用它来使用普通的C.这个库有一个名为checkError()
的函数。此函数抛出与对象内发生的错误相关的异常。在C ++包装器中,我正在捕获此错误,mallocing一个C兼容的结构,将错误消息和信息分配给错误结构变量,然后我将指针传递回结构。这一切都很好,花花公子,但是一旦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_check_error
中wrapper.cpp
的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;
}
}
在wrapper_check_error()
中使用main.c
的普通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以及其他网站,但我没有找到任何能回答我问题的内容。
我从项目中摘录了代码,缩短了代码,并重命名了变量/函数。除了一些错误检查,如果我在某种程度上没有注意到的代码中有明显的错误,请发表评论,以便我可以修改它。如果有任何不清楚的地方,请在评论中告诉我,我会尽力更新问题并澄清。
答案 0 :(得分:3)
由于有三个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;
需要对free()
进行3次调用:
free(errorMsg->typeAsText);
free(errorMsg->what);
free(errorMsg);
作为旁注,根据定义,sizeof(char)
为1,所以没有必要为此做任何特别的事情。
正如另一方面所说,我建议使用strdup()
而不是容易出错的杂乱,如:
cErr->what = (char *)malloc((strlen(errWhat)+1) * charSize);
strcpy(cErr->what, errWhat);