fix memory leak during export
parent
6f8d96b57e
commit
ccd13436da
|
@ -189,42 +189,42 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
|
|||
continue;
|
||||
if (aiProps[k].pKey) {
|
||||
switch (m3d_propertytypes[k].format) {
|
||||
case m3dpf_color:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, c) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, mkColor(&c));
|
||||
break;
|
||||
case m3dpf_float:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, f) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id,
|
||||
/* not (uint32_t)f, because we don't want to convert
|
||||
case m3dpf_color:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, c) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, mkColor(&c));
|
||||
break;
|
||||
case m3dpf_float:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, f) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id,
|
||||
/* not (uint32_t)f, because we don't want to convert
|
||||
* it, we want to see it as 32 bits of memory */
|
||||
*((uint32_t *)&f));
|
||||
break;
|
||||
case m3dpf_uint8:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS) {
|
||||
// special conversion for illumination model property
|
||||
if (m3d_propertytypes[k].id == m3dp_il) {
|
||||
switch (j) {
|
||||
case aiShadingMode_NoShading: j = 0; break;
|
||||
case aiShadingMode_Phong: j = 2; break;
|
||||
default: j = 1; break;
|
||||
}
|
||||
*((uint32_t *)&f));
|
||||
break;
|
||||
case m3dpf_uint8:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS) {
|
||||
// special conversion for illumination model property
|
||||
if (m3d_propertytypes[k].id == m3dp_il) {
|
||||
switch (j) {
|
||||
case aiShadingMode_NoShading: j = 0; break;
|
||||
case aiShadingMode_Phong: j = 2; break;
|
||||
default: j = 1; break;
|
||||
}
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
break;
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aiTxProps[k].pKey &&
|
||||
|
@ -292,8 +292,8 @@ void ExportSceneM3D(
|
|||
// Prototyped and registered in Exporter.cpp
|
||||
void ExportSceneM3DA(
|
||||
const char *,
|
||||
IOSystem*,
|
||||
const aiScene*,
|
||||
IOSystem *,
|
||||
const aiScene *,
|
||||
const ExportProperties *
|
||||
|
||||
) {
|
||||
|
@ -312,7 +312,9 @@ void ExportSceneM3DA(
|
|||
M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) :
|
||||
mScene(pScene),
|
||||
mProperties(pProperties),
|
||||
outfile() {}
|
||||
outfile() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void M3DExporter::doExport(
|
||||
|
@ -352,6 +354,9 @@ void M3DExporter::doExport(
|
|||
// explicitly release file pointer,
|
||||
// so we don't have to rely on class destruction.
|
||||
outfile.reset();
|
||||
|
||||
M3D_FREE(m3d->name);
|
||||
m3d->name = nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -50,15 +50,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifdef ASSIMP_USE_M3D_READFILECB
|
||||
|
||||
# if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
|
||||
# define threadlocal thread_local
|
||||
# else
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
|
||||
# define threadlocal __declspec(thread)
|
||||
# else
|
||||
# define threadlocal
|
||||
# endif
|
||||
# endif
|
||||
#if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
|
||||
#define threadlocal thread_local
|
||||
#else
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
|
||||
#define threadlocal __declspec(thread)
|
||||
#else
|
||||
#define threadlocal
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
@ -66,37 +66,37 @@ extern "C" {
|
|||
threadlocal void *m3dimporter_pIOHandler;
|
||||
|
||||
unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
|
||||
ai_assert(nullptr != fn);
|
||||
ai_assert(nullptr != size);
|
||||
std::string file(fn);
|
||||
std::unique_ptr<Assimp::IOStream> pStream(
|
||||
(reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
|
||||
size_t fileSize = 0;
|
||||
unsigned char *data = NULL;
|
||||
// sometimes pStream is nullptr in a single-threaded scenario too for some reason
|
||||
// (should be an empty object returning nothing I guess)
|
||||
if (pStream) {
|
||||
fileSize = pStream->FileSize();
|
||||
// should be allocated with malloc(), because the library will call free() to deallocate
|
||||
data = (unsigned char *)malloc(fileSize);
|
||||
if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
|
||||
pStream.reset();
|
||||
*size = 0;
|
||||
// don't throw a deadly exception, it's not fatal if we can't read an external asset
|
||||
return nullptr;
|
||||
}
|
||||
pStream.reset();
|
||||
}
|
||||
*size = (int)fileSize;
|
||||
return data;
|
||||
ai_assert(nullptr != fn);
|
||||
ai_assert(nullptr != size);
|
||||
std::string file(fn);
|
||||
std::unique_ptr<Assimp::IOStream> pStream(
|
||||
(reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
|
||||
size_t fileSize = 0;
|
||||
unsigned char *data = NULL;
|
||||
// sometimes pStream is nullptr in a single-threaded scenario too for some reason
|
||||
// (should be an empty object returning nothing I guess)
|
||||
if (pStream) {
|
||||
fileSize = pStream->FileSize();
|
||||
// should be allocated with malloc(), because the library will call free() to deallocate
|
||||
data = (unsigned char *)malloc(fileSize);
|
||||
if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
|
||||
pStream.reset();
|
||||
*size = 0;
|
||||
// don't throw a deadly exception, it's not fatal if we can't read an external asset
|
||||
return nullptr;
|
||||
}
|
||||
pStream.reset();
|
||||
}
|
||||
*size = (int)fileSize;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace Assimp {
|
||||
M3DWrapper::M3DWrapper() {
|
||||
// use malloc() here because m3d_free() will call free()
|
||||
m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
|
||||
// use malloc() here because m3d_free() will call free()
|
||||
m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
|
||||
}
|
||||
|
||||
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
|
||||
// pass this IOHandler to the C callback in a thread-local pointer
|
||||
m3dimporter_pIOHandler = pIOHandler;
|
||||
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
|
||||
// Clear the C callback
|
||||
m3dimporter_pIOHandler = nullptr;
|
||||
// pass this IOHandler to the C callback in a thread-local pointer
|
||||
m3dimporter_pIOHandler = pIOHandler;
|
||||
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
|
||||
// Clear the C callback
|
||||
m3dimporter_pIOHandler = nullptr;
|
||||
#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
|
||||
}
|
||||
|
||||
M3DWrapper::~M3DWrapper() {
|
||||
reset();
|
||||
reset();
|
||||
}
|
||||
|
||||
void M3DWrapper::reset() {
|
||||
ClearSave();
|
||||
if (m3d_)
|
||||
m3d_free(m3d_);
|
||||
m3d_ = nullptr;
|
||||
ClearSave();
|
||||
if (m3d_) {
|
||||
m3d_free(m3d_);
|
||||
}
|
||||
m3d_ = nullptr;
|
||||
}
|
||||
|
||||
unsigned char *M3DWrapper::Save(int quality, int flags, unsigned int &size) {
|
||||
#if (!(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER))
|
||||
ClearSave();
|
||||
saved_output_ = m3d_save(m3d_, quality, flags, &size);
|
||||
return saved_output_;
|
||||
ClearSave();
|
||||
saved_output_ = m3d_save(m3d_, quality, flags, &size);
|
||||
return saved_output_;
|
||||
#else
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void M3DWrapper::ClearSave() {
|
||||
if (saved_output_)
|
||||
M3D_FREE(saved_output_);
|
||||
saved_output_ = nullptr;
|
||||
if (saved_output_)
|
||||
M3D_FREE(saved_output_);
|
||||
saved_output_ = nullptr;
|
||||
}
|
||||
} // namespace Assimp
|
||||
|
||||
|
|
Loading…
Reference in New Issue