Skip Menu |
Report information
Id: 132690
Status: open
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: keuchel [at] rainer-keuchel.de
Cc:
AdminCc:

Operating System: Win32
PatchStatus: (no value)
Severity: low
Type: core
Perl Version: (no value)
Fixed In: (no value)



From: Rainer Keuchel <keuchel [...] rainer-keuchel.de>
Date: Sun, 7 Jan 2018 19:41:10 +0100
Subject: PERL: Change proposal for win32/vmem.h
To: perlbug [...] perl.org
Download (untitled) / with headers
text/plain 1.8k

I had a problems with Inline::CPP on Windows/MingW.

DLLs built with Inline::CPP use msvcrt malloc/free.

When USE_LINKED_LIST is defined in vmem.h
then memory from a DLL built by Inline:CPP cannot be freed
and a SEGV is generated.

I would suggest to check if the pointer to free belongs to the process heap
and free it accordingly with free().

With this change everything is fine..


void VMem::Free(void* pMem)
{
#ifdef _USE_LINKED_LIST
    if (pMem) {
      size_t s;
      HANDLE hHeap;

      PMEMORY_BLOCK_HEADER ptr = (PMEMORY_BLOCK_HEADER)(((char*)pMem)-sizeof(MEMORY_BLOCK_HEADER));
   
      if (ptr->owner != this) {

    // can be block from msvcrt malloc when using Inline::CPP!
    hHeap = GetProcessHeap();
    s = HeapSize(hHeap, 0, pMem);

    if(s == (size_t) -1)
      {
        dTHX;
        Perl_warn(aTHX_ "ptr %p is not alloc'ed from msvcrt malloc", pMem);
      }
    else
      {
        //dTHX;
        //Perl_warn(aTHX_ "ptr %p is alloc'ed from msvcrt malloc", pMem);
        m_pfree(pMem);
        return;
      }
   
      
        if (ptr->owner) {
#if 1
        dTHX;
            int *nowhere = NULL;
            Perl_warn(aTHX_ "Free to wrong pool %p not %p",this,ptr->owner);
                *nowhere = 0; /* this segfault is deliberate,
                                 so you can see the stack trace */
#else
                ptr->owner->Free(pMem);   
#endif
        }
        return;
        }
    GetLock();
    UnlinkBlock(ptr);
    ptr->owner = NULL;
    m_pfree(ptr);
    FreeLock();
    }
#else
    m_pfree(pMem);
#endif
}



RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 2.5k
On Sun, 07 Jan 2018 10:48:37 -0800, keuchel@rainer-keuchel.de wrote: Show quoted text
> I had a problems with Inline::CPP on Windows/MingW. > > DLLs built with Inline::CPP use msvcrt malloc/free. > > When USE_LINKED_LIST is defined in vmem.h > then memory from a DLL built by Inline:CPP cannot be freed > and a SEGV is generated. > > I would suggest to check if the pointer to free belongs to the process heap > and free it accordingly with free(). > > With this change everything is fine..
Calling HeapSize on random pointers, with there being NO guarantee the pointer was allocated by the kernel32.dll heap allocater isn't safe. While modern (>= Vista or XP) checksum/XOR the 8/16 byte malloc header before pointer to detect corruption, that is implementation specific and undependable. I think your problem is Inline::CPP doesnt do a #include "XSUB.h", so the #define free(x) never happens that most Win32 XS code has that maps the free token to perl's own allocator. It is a long running problem on Win32 perl. I think the original reason for hooking free() in XS code was for ithread/psuedo-fork cleanup/anti-leaking on psuedo-proc exit so perl can cleanly free "global" pointers from C-ish (not using perl data structures) XS code that keep things allocated forever because it assumes the OS will clean it up on process exit (but perl has psuedo-procs). That linked list code also smoothes over any P5P memory leaks that perl_destruct doesn't free by accident. There is yet another problem about multiple CRTs in a process and they generate their own Kernel32 Heap objects/pools too, they dont use heap returned by GetProcessHeap. Use VMMap tool on a perl process, click orange Heap, then in the bottom there will be atleast 2 heap IDs (AKA pools), one is GetProcessHeap, other is CRT specific and Perl uses that. If you wind up in CRT hell, each new CRT in the process will make its own pool. Many 3rd party and MS DLLs like to make their Heap pools too. Some C libraries like to add their own header to an object/allocation they give you and they dont give you a pointer to the start of the allocation but a pointer to somewhere inside the allocation. These libraries also tell you to free the resource ONLY by using their functions, not a generic ISO C free(). You need to figure out what is going on with the headers, make a .i file, run it through gnu indent, and figure out if your Inline::CPP code is perl/XS aware or not and what is the final C symbol name of the callsite of that free() in your code. "NO_XSLOCKS" is the define that usually turns off perl hooking C std lib functions. -- bulk88 ~ bulk88 at hotmail.com


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org