LibXML2 在 Python/ctypes 中封装时无法释放内存

LibXML2 failing to free memory when encapsulated in Python/ctypes

提问人:Danny Holstein 提问时间:5/2/2023 最后编辑:ProgmanDanny Holstein 更新时间:5/5/2023 访问量:85

问:

我的 Python 脚本是:

def xmlEncodeSpecialChars(doc: xmlDoc, input: str) -> str:
    '''
    Do a global encoding of a string, replacing the predefined entities this routine is reentrant, and result must be deallocated.

        doc:        the document containing the string
        input:      A string to convert to XML.
        Returns:    A newly allocated string with the substitution done.'''
        
    libXML = LibXML2() # DSO/DLL 

    libXML.xmlEncodeSpecialChars.restype = ctypes.c_char_p
    libXML.xmlEncodeSpecialChars.argtypes = ctypes.c_void_p, ctypes.c_char_p, 

    output: ctypes.c_char_p = libXML.xmlEncodeSpecialChars(doc, input.encode()); 
    Err = xmlGetLastError()
    if Err: raise LibErr(Err)
    ans = output.decode()
# free memory
    libXML.xmlMemFree.argtypes = ctypes.c_char_p, ;
    libXML.xmlMemFree(output)
    
    return ans

它正确地返回一个转义字符串,但 xmlMemFree() 在 Python 中生成一个,尽管对同一 DLL 的等效 C 调用工作得很好。Memory tag error

如何设置内存空闲操作?ctypes

---编辑---

最低可重现 (Linux) 设置为:

def xmlEncodeSpecialChars(doc: xmlDoc, input: str) -> str:
    '''
    Do a global encoding of a string, replacing the predefined entities this routine is reentrant, and result must be deallocated.

        doc:        the document containing the string
        input:      A string to convert to XML.
        Returns:    A newly allocated string with the substitution done.'''
    
    libXML = ctypes.CDLL ("libxml2.so.2") # DSO/DLL 

    libXML.xmlEncodeSpecialChars.restype = ctypes.c_void_p
    libXML.xmlEncodeSpecialChars.argtypes = ctypes.c_void_p, ctypes.c_char_p, 

    output: ctypes.c_void_p = libXML.xmlEncodeSpecialChars(doc, input.encode()); 

    Err = xmlGetLastError() #   check for library error
    if Err: raise LibErr(Err)

    ans = ctypes.cast(output, ctypes.c_char_p).value.decode()                   #   convert to Python str

    libXML.xmlMemFree.argtypes = ctypes.c_void_p, ;libXML.xmlMemFree(output);   #   free memory, FIXME

    return ans

print(xmlEncodeSpecialChars(None, "<root>Some text with < and > characters</root>"))
python libxml2

评论

2赞 jasonharper 5/2/2023
这回答了你的问题吗?Python ctypes:如何释放内存?出现无效指针错误
0赞 Tim Roberts 5/2/2023
你的标题说 ,但问题出在 ,这就是问题的根源。 被区别对待。无论如何,你为什么要去找这个麻烦?Python 包含一个全面且集成良好的 XML 模块,可以直接执行此操作。c_void_pc_char_pc_char_p
0赞 Danny Holstein 5/2/2023
@TimRoberts,我一直在将 LibXML2 与我所有的 C/C++ 代码、LabVIEW、Excel VBA 和 Python 一起使用 - 我的课程运行良好,而且我对内外都了如指掌 - 这就是原因。所有这些语言都可以直接共享相同的 DOM、节点和 XPath 解析器。
1赞 Mark Tolonen 5/2/2023
@TimRoberts Python 不知道返回的 char* 是否从堆中分配,并且不会自动释放内存。Python 字符串是一个副本,但原始内存在没有可用的情况下丢失。
1赞 HolyBlackCat 8/25/2023
不要将反对票解释为人身攻击,它们只是表明问题需要解决。例如,请参阅 ()。# 4.4

答:

0赞 Mark Tolonen 5/3/2023 #1

在 中,转换以 null 结尾的 C 并返回一个 Python 对象。指针丢失。ctypesc_char_pchar*bytes

使用或维护指针。 可用于读取返回地址处以 null 结尾的字符串。c_void_pPOINTER(c_char)string_at

未经测试:

def xmlEncodeSpecialChars(doc: xmlDoc, input: str) -> str:
    '''
    Do a global encoding of a string, replacing the predefined entities this routine is reentrant, and result must be deallocated.

        doc:        the document containing the string
        input:      A string to convert to XML.
        Returns:    A newly allocated string with the substitution done.'''
    libXML = LibXML2() # DSO/DLL 

    libXML.xmlEncodeSpecialChars.restype = ctypes.c_void_p
    libXML.xmlEncodeSpecialChars.argtypes = ctypes.c_void_p, ctypes.c_char_p

    output: ctypes.c_void_p = libXML.xmlEncodeSpecialChars(doc, input.encode())
    Err = xmlGetLastError()
    if Err: raise LibErr(Err)
    ans = ctypes.string_at(output).decode()
# free memory
    libXML.xmlMemFree.argtypes = ctypes.c_void_p,
    libXML.xmlMemFree.restype = None
    libXML.xmlMemFree(output)
    return ans

评论

0赞 Danny Holstein 5/3/2023
我已经尝试过,并确信它会起作用。Memory tag error occurs :0x55580b699828 bye xmlMemFree(0x55580b699850) error xmlMallocBreakpoint reached on block 0
0赞 Danny Holstein 5/3/2023
我很高兴知道指针的转换和丢失。看来我还是丢了指针 😢c_char_p
0赞 Mark Tolonen 5/3/2023
@DannyHolstein 如果这不起作用,您还有其他问题。制作一个最小的可重现示例,并提供指向所用 DLL 的链接。我找不到任何文档链接。它也可以帮助了解它在 C 代码中的使用方式。使用 ?xmlEncodeSpecialCharsstring_at
0赞 Danny Holstein 5/3/2023
我确定!只是为了咯咯笑,我把指针传递给了它,它工作得很好!xmlStrlen()