我正在处理一个C++库的包装,我需要使用plain C.该库具有一个名为checkError()
的函数。该函数会引发与对象内发生的错误相关的异常。在C++包装器中,我捕获了这个错误,mallocing一个C兼容的结构,将错误消息和信息分配给错误结构变量,然后我将指针传递回结构。这一切都很好,但是我一直担心C调用函数处理完结构后会发生内存泄漏。释放包含malloc'd字符串的malloc'd结构
对于这个问题,我们假设该库的对象称为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
C++实现的wrapper_check_error
内wrapper.cpp
:
/* 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
仍然在堆上,我会写一个函数来释放结构成员,然后释放结构本身。但是,如果有必要,我只想这样做。
如果有人可以提供一些关于此的指导/见解,将不胜感激。
谢谢。
如果这个问题是重复的,我很抱歉。如果是这样,请将问题指向类似问题的方向,以便我可以阅读那里的答案。我搜索了以及其他网站,但我还没有找到任何答案我的问题。
我从我的项目中摘录了代码,缩短了代码,并重命名了变量/函数。除了一些错误检查之外,如果代码中存在明显的错误,我不知何故,请发表评论,以便我可以修改它。如果有什么不清楚的地方,请在评论中告诉我,我会尽我所能来更新问题并进行澄清。
'free'不是递归(这是不可能的,它无法知道的方式你有其他的指向内部块,并希望保持它们)。您必须手动释放成员指针指向的块。 – 2014-10-17 18:57:10
谢谢,很高兴知道。我知道'free'接收一个'void *'作为参数,所以这让我更加不确定是否释放了整个结构。也就是说,如果C++包装器是用托管C++实现而不是本地编写的,情况会不会改变?例如,如果包装器是用MSVC而不是本地C++编写的,那么释放结构本身就成为一种有效的方法来删除其中的C字符串?我只问,因为MSVC有一个内置的垃圾收集器。我计划使用本机C++来保持项目,所以我只是将MSVC作为一个学术问题。 – SpencerD 2014-10-17 19:05:53