TheAssemblyArmada / Thyme

An open source re-implementation of Generals : Zero Hour written in C++.
GNU General Public License v2.0
569 stars 54 forks source link

w3dview texture crash 2 #1135

Open xezon opened 1 month ago

xezon commented 1 month ago
>   [Inline Frame] w3dview.exe!MemoryPoolSingleBlock::Add_Block_To_List(MemoryPoolSingleBlock *) Line 78    C++
    [Inline Frame] w3dview.exe!MemoryPoolSingleBlock::Set_Next_Free(MemoryPoolSingleBlock * next) Line 85   C++
    [Inline Frame] w3dview.exe!MemoryPoolBlob::Free_Single_Block(MemoryPoolSingleBlock *) Line 111  C++
    w3dview.exe!MemoryPool::Free_Block(void * block) Line 149   C++
    w3dview.exe!DynamicMemoryAllocator::Free_Bytes(void * block) Line 176   C++
    w3dview.exe!operator delete[](void * ptr) Line 218  C++
    w3dview.exe!StringClass::Free_String() Line 101 C++
    [Inline Frame] w3dview.exe!StringClass::{dtor}() Line 173   C++
    w3dview.exe!SimpleFileFactoryClass::Get_File(const char * filename) Line 106    C++
    w3dview.exe!auto_file_ptr::auto_file_ptr(FileFactoryClass * fact, const char * filename) Line 34    C++
    w3dview.exe!DDSFileClass::DDSFileClass(const char * filename, unsigned int reduction_factor) Line 61    C++
    w3dview.exe!TextureLoadTaskClass::Get_Texture_Information(const char * name, unsigned int & reduction, unsigned int & width, unsigned int & height, unsigned int & depth, WW3DFormat & format, unsigned int & levels, bool use_dds) Line 713    C++
    w3dview.exe!TextureLoadTaskClass::Begin_Compressed_Load() Line 177  C++
    w3dview.exe!TextureLoadTaskClass::Begin_Load() Line 571 C++
    w3dview.exe!TextureLoader::Begin_Load_And_Queue(TextureLoadTaskClass * task) Line 505   C++
    w3dview.exe!TextureLoader::Request_Background_Loading(TextureBaseClass * texture) Line 322  C++
    w3dview.exe!TextureClass::Init() Line 331   C++
    w3dview.exe!DX8Wrapper::Apply_Render_State_Changes() Line 1546  C++
    w3dview.exe!DX8Wrapper::Draw(unsigned int primitive_type, unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, unsigned short vertex_count) Line 1432 C++
    w3dview.exe!DX8Wrapper::Draw_Triangles(unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, unsigned short vertex_count) Line 1519    C++
    [Inline Frame] w3dview.exe!DX8PolygonRendererClass::Render(int offset) Line 73  C++
    w3dview.exe!DX8TextureCategoryClass::Render() Line 655  C++
    w3dview.exe!DX8RigidFVFCategoryContainer::Render() Line 1388    C++
    w3dview.exe!Render_FVF_Category_Container_List(MultiListClass<DX8FVFCategoryContainer> & containers) Line 324   C++
    w3dview.exe!DX8MeshRendererClass::Flush() Line 342  C++
    w3dview.exe!W3D::Flush(RenderInfoClass & rinfo) Line 370    C++
    w3dview.exe!W3D::Render(SceneClass * scene, CameraClass * cam, bool clear, bool clearz, const Vector3 & color) Line 340 C++
    w3dview.exe!CGraphicView::Render(int update, unsigned int time) Line 599    C++
    w3dview.exe!CGraphicView::WindowProc(unsigned int message, unsigned int wParam, long lParam) Line 87    C++
    [External Code] 
    [Frames below may be incorrect and/or missing, no symbols loaded for mfc140.dll]    
Exception thrown: write access violation.
mp_blob->**m_firstFreeBlock** was 0x7449656C.
FileClass *SimpleFileFactoryClass::Get_File(const char *filename)
{
    StringClass stripped_name(248, true);

    if (m_isStripPath) {
        const char *separator = strrchr(filename, '\\');

        if (separator != nullptr) {
            stripped_name = separator + 1;
        } else {
            stripped_name = filename;
        }
    } else {
        stripped_name = filename;
    }

    BufferedFileClass *file = new BufferedFileClass;
    captainslog_assert(file);

    StringClass new_name(stripped_name, true); // Crashes deleting this string on function return.

    if (!Is_Full_Path(stripped_name)) {
        CriticalSectionClass::LockClass lock(m_mutex);

        if (!m_subDirectory.Is_Empty()) {
            StringClass subdir(m_subDirectory, true);

            if (strchr(subdir, ';')) {
                for (const char *token = strtok(subdir.Peek_Buffer(), ";"); token; token = strtok(nullptr, ";")) {
                    new_name.Format("%s%s", token, stripped_name.Peek_Buffer());
                    file->Set_Name(new_name);

                    if (file->Open(1)) {
                        file->Close();
                        break;
                    }
                }
            } else {
                new_name.Format("%s%s", m_subDirectory.Peek_Buffer(), stripped_name.Peek_Buffer());
            }
        }
    }

    file->Set_Name(new_name);
    return file;
}
  Name Value Type
new_name {m_buffer=0x02eb3b9c "D:\Projects\TheSuperHackers\GeneralsFiles\Generals-108-GeneralsZH-104-Loose\Art\W3D\" } StringClass
  ▶ m_buffer 0x02eb3b9c "D:\Projects\TheSuperHackers\GeneralsFiles\Generals-108-GeneralsZH-104-Loose\Art\W3D\" char *

I suspect this is a double free.

xezon commented 1 month ago

This crash still happens.

xezon commented 1 month ago

I don't know what the problem is. Could be a race condition?! There is another thread that also loads a texture at the time of the crash:

    ntdll.dll!_NtCreateFile@44()    Unknown
    KernelBase.dll!_CreateFileInternal@24() Unknown
    KernelBase.dll!_CreateFileW@28()    Unknown
    KernelBase.dll!_CreateFileA@28()    Unknown
    w3dview.exe!RawFileClass::Open(int rights) Line 198 C++
    w3dview.exe!SimpleFileFactoryClass::Get_File(const char * filename) Line 94 C++
>   w3dview.exe!auto_file_ptr::auto_file_ptr(FileFactoryClass * fact, const char * filename) Line 34    C++
    w3dview.exe!DDSFileClass::Load() Line 584   C++
    w3dview.exe!TextureLoadTaskClass::Load_Compressed_Mipmap() Line 336 C++
    w3dview.exe!TextureLoadTaskClass::Load() Line 600   C++
    w3dview.exe!LoaderThreadClass::Thread_Function() Line 98    C++
    w3dview.exe!ThreadClass::Internal_Thread_Function(void * params) Line 99    C++
    ucrtbase.dll!762fc5b3() Unknown
    [Frames below may be incorrect and/or missing, no symbols loaded for ucrtbase.dll]  
    kernel32.dll!771cfcc9() Unknown
    ntdll.dll!__RtlUserThreadStart()    Unknown
    ntdll.dll!__RtlUserThreadStart@8()  Unknown