fix memory leak during export

pull/2885/head
kimkulling 2020-03-25 16:37:43 +01:00
parent 6f8d96b57e
commit ccd13436da
2 changed files with 94 additions and 88 deletions

View File

@ -189,42 +189,42 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
continue; continue;
if (aiProps[k].pKey) { if (aiProps[k].pKey) {
switch (m3d_propertytypes[k].format) { switch (m3d_propertytypes[k].format) {
case m3dpf_color: case m3dpf_color:
if (mat->Get(aiProps[k].pKey, aiProps[k].type, if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, c) == AI_SUCCESS) aiProps[k].index, c) == AI_SUCCESS)
addProp(&m3d->material[mi], addProp(&m3d->material[mi],
m3d_propertytypes[k].id, mkColor(&c)); m3d_propertytypes[k].id, mkColor(&c));
break; break;
case m3dpf_float: case m3dpf_float:
if (mat->Get(aiProps[k].pKey, aiProps[k].type, if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, f) == AI_SUCCESS) aiProps[k].index, f) == AI_SUCCESS)
addProp(&m3d->material[mi], addProp(&m3d->material[mi],
m3d_propertytypes[k].id, m3d_propertytypes[k].id,
/* not (uint32_t)f, because we don't want to convert /* not (uint32_t)f, because we don't want to convert
* it, we want to see it as 32 bits of memory */ * it, we want to see it as 32 bits of memory */
*((uint32_t *)&f)); *((uint32_t *)&f));
break; break;
case m3dpf_uint8: case m3dpf_uint8:
if (mat->Get(aiProps[k].pKey, aiProps[k].type, if (mat->Get(aiProps[k].pKey, aiProps[k].type,
aiProps[k].index, j) == AI_SUCCESS) { aiProps[k].index, j) == AI_SUCCESS) {
// special conversion for illumination model property // special conversion for illumination model property
if (m3d_propertytypes[k].id == m3dp_il) { if (m3d_propertytypes[k].id == m3dp_il) {
switch (j) { switch (j) {
case aiShadingMode_NoShading: j = 0; break; case aiShadingMode_NoShading: j = 0; break;
case aiShadingMode_Phong: j = 2; break; case aiShadingMode_Phong: j = 2; break;
default: j = 1; break; default: j = 1; break;
}
} }
addProp(&m3d->material[mi],
m3d_propertytypes[k].id, j);
} }
break; addProp(&m3d->material[mi],
default: m3d_propertytypes[k].id, j);
if (mat->Get(aiProps[k].pKey, aiProps[k].type, }
aiProps[k].index, j) == AI_SUCCESS) break;
addProp(&m3d->material[mi], default:
m3d_propertytypes[k].id, j); if (mat->Get(aiProps[k].pKey, aiProps[k].type,
break; aiProps[k].index, j) == AI_SUCCESS)
addProp(&m3d->material[mi],
m3d_propertytypes[k].id, j);
break;
} }
} }
if (aiTxProps[k].pKey && if (aiTxProps[k].pKey &&
@ -292,8 +292,8 @@ void ExportSceneM3D(
// Prototyped and registered in Exporter.cpp // Prototyped and registered in Exporter.cpp
void ExportSceneM3DA( void ExportSceneM3DA(
const char *, const char *,
IOSystem*, IOSystem *,
const aiScene*, const aiScene *,
const ExportProperties * const ExportProperties *
) { ) {
@ -312,7 +312,9 @@ void ExportSceneM3DA(
M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) : M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) :
mScene(pScene), mScene(pScene),
mProperties(pProperties), mProperties(pProperties),
outfile() {} outfile() {
// empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void M3DExporter::doExport( void M3DExporter::doExport(
@ -352,6 +354,9 @@ void M3DExporter::doExport(
// explicitly release file pointer, // explicitly release file pointer,
// so we don't have to rely on class destruction. // so we don't have to rely on class destruction.
outfile.reset(); outfile.reset();
M3D_FREE(m3d->name);
m3d->name = nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -50,15 +50,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ASSIMP_USE_M3D_READFILECB #ifdef ASSIMP_USE_M3D_READFILECB
# if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards #if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
# define threadlocal thread_local #define threadlocal thread_local
# else #else
# if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013 #if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
# define threadlocal __declspec(thread) #define threadlocal __declspec(thread)
# else #else
# define threadlocal #define threadlocal
# endif #endif
# endif #endif
extern "C" { extern "C" {
@ -66,37 +66,37 @@ extern "C" {
threadlocal void *m3dimporter_pIOHandler; threadlocal void *m3dimporter_pIOHandler;
unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
ai_assert(nullptr != fn); ai_assert(nullptr != fn);
ai_assert(nullptr != size); ai_assert(nullptr != size);
std::string file(fn); std::string file(fn);
std::unique_ptr<Assimp::IOStream> pStream( std::unique_ptr<Assimp::IOStream> pStream(
(reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb")); (reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
size_t fileSize = 0; size_t fileSize = 0;
unsigned char *data = NULL; unsigned char *data = NULL;
// sometimes pStream is nullptr in a single-threaded scenario too for some reason // sometimes pStream is nullptr in a single-threaded scenario too for some reason
// (should be an empty object returning nothing I guess) // (should be an empty object returning nothing I guess)
if (pStream) { if (pStream) {
fileSize = pStream->FileSize(); fileSize = pStream->FileSize();
// should be allocated with malloc(), because the library will call free() to deallocate // should be allocated with malloc(), because the library will call free() to deallocate
data = (unsigned char *)malloc(fileSize); data = (unsigned char *)malloc(fileSize);
if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) { if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
pStream.reset(); pStream.reset();
*size = 0; *size = 0;
// don't throw a deadly exception, it's not fatal if we can't read an external asset // don't throw a deadly exception, it's not fatal if we can't read an external asset
return nullptr; return nullptr;
} }
pStream.reset(); pStream.reset();
} }
*size = (int)fileSize; *size = (int)fileSize;
return data; return data;
} }
} }
#endif #endif
namespace Assimp { namespace Assimp {
M3DWrapper::M3DWrapper() { M3DWrapper::M3DWrapper() {
// use malloc() here because m3d_free() will call free() // use malloc() here because m3d_free() will call free()
m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t)); m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
} }
M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) { M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) {
@ -105,41 +105,42 @@ M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &b
} }
#ifdef ASSIMP_USE_M3D_READFILECB #ifdef ASSIMP_USE_M3D_READFILECB
// pass this IOHandler to the C callback in a thread-local pointer // pass this IOHandler to the C callback in a thread-local pointer
m3dimporter_pIOHandler = pIOHandler; m3dimporter_pIOHandler = pIOHandler;
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr); m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
// Clear the C callback // Clear the C callback
m3dimporter_pIOHandler = nullptr; m3dimporter_pIOHandler = nullptr;
#else #else
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr); m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
#endif #endif
} }
M3DWrapper::~M3DWrapper() { M3DWrapper::~M3DWrapper() {
reset(); reset();
} }
void M3DWrapper::reset() { void M3DWrapper::reset() {
ClearSave(); ClearSave();
if (m3d_) if (m3d_) {
m3d_free(m3d_); m3d_free(m3d_);
m3d_ = nullptr; }
m3d_ = nullptr;
} }
unsigned char *M3DWrapper::Save(int quality, int flags, unsigned int &size) { unsigned char *M3DWrapper::Save(int quality, int flags, unsigned int &size) {
#if (!(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER)) #if (!(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER))
ClearSave(); ClearSave();
saved_output_ = m3d_save(m3d_, quality, flags, &size); saved_output_ = m3d_save(m3d_, quality, flags, &size);
return saved_output_; return saved_output_;
#else #else
return nullptr; return nullptr;
#endif #endif
} }
void M3DWrapper::ClearSave() { void M3DWrapper::ClearSave() {
if (saved_output_) if (saved_output_)
M3D_FREE(saved_output_); M3D_FREE(saved_output_);
saved_output_ = nullptr; saved_output_ = nullptr;
} }
} // namespace Assimp } // namespace Assimp