我正在處理一個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