当前位置: 首页 > 面试题库 >

Python CTYPE:如何释放内存?获取无效的指针错误

穆承运
2023-03-14
问题内容

我想从带有ctypes的C / C ++库中获取一些字符串到python中。我的代码如下所示:

lib中的代码:

const char* get(struct something *x) 
{
    [...]
    // buf is a stringstream
   return strdup(buf.str().c_str());
}

void freeme(char *ptr)
{
    free(ptr);
}

Python代码:

fillprototype(lib.get, c_char_p, POINTER(some_model)])
fillprototype(lib.freeme, None, [c_char_p])

// what i want to do here: get a string into python so that i can work
// with it and release the memory in the lib.
c_str = lib.get(some_model)
y = ''.join(c_str)
lib.freeme(c_str)

如果我print()c_str,一切都在那里。问题是(或似乎是)在最后一行Python中。我无法释放内存-
库得到了错误的指针。我在这里做错了什么?(并且请不要建议boost :: python左右)。

*** glibc detected *** python2: munmap_chunk(): invalid pointer: 0x00000000026443fc ***

问题答案:

正如David Schwartz指出的那样,如果将restype设置为c_char_p,则ctypes将返回常规的Python字符串对象。解决此问题的一种简单方法是使用avoid *并强制转换结果:

string.c:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char *get(void)
{
    char *buf = "Hello World";
    char *new_buf = strdup(buf);
    printf("allocated address: %p\n", new_buf);
    return new_buf;
}

void freeme(char *ptr)
{
    printf("freeing address: %p\n", ptr);
    free(ptr);
}

Python用法:

from ctypes import *

lib = cdll.LoadLibrary('./string.so')
lib.freeme.argtypes = c_void_p,
lib.freeme.restype = None
lib.get.argtypes = []
lib.get.restype = c_void_p

>>> ptr = lib.get()
allocated address: 0x9facad8
>>> hex(ptr)
'0x9facad8'
>>> cast(ptr, c_char_p).value
'Hello World'
>>> lib.freeme(ptr)
freeing address: 0x9facad8

您还可以使用的子类c_char_p。事实证明,ctypes不会getfunc为简单类型的子类调用。

class c_char_p_sub(c_char_p):
    pass

lib.get.restype = c_char_p_sub

value属性返回字符串。您可以将参数保留freeme为更通用c_void_p。那可以接受任何指针类型或整数地址。



 类似资料:
  • 根据我的理解, free()用于释放之前使用malloc分配的内存。 在我下面的片段中,我释放了我分配的内存。但是即使释放后我也能够访问指针?这怎么可能? free如何在内部工作?

  • 我正在XE3中创建一个新应用程序,但使用在D2007中创建的一些单元。 我“在释放TStringList数据项时收到错误。这是创建数据项FSQL的代码: 以下是获取错误的代码: 错误发生在“FreeAndNil(FSQL);”上。我尝试了“FSQL. Free”,得到了相同的结果。 这是我得到的错误: 项目:PayrUpdate。exe引发了异常类EInvalidPointer,并显示消息“指针操

  • 我是gccgo新手,我需要编译/运行以下代码的帮助(这在“标准”go编译器中可以正常工作(抱歉,我不知道正确的名称)): 我的gcc: 我的第一个文件: 我的第二个文件: 我的编译错误: 我做错了什么?

  • 问题内容: 我是新手,尝试制作一个简单的网络爬虫。我不断收到“紧急情况:运行时错误:无效的内存地址或nil指针取消引用”,并且不知道如何解决该问题。我有一个“ advancedFetcher”功能和一个“basicFetcher”功能,在任何一个下都出现相同的错误。这个答案建议检查每个错误(我认为是错误),但仍然出现错误。谢谢! 编辑#1: 问题答案: 您的程序在惊慌之前打印错误吗?如果没有记错,

  • 我是新手,试图制作一个简单的网络爬虫。我一直收到“恐慌:运行时错误:无效的内存地址或零指针取消引用”,不知道如何解决这个问题。我有一个“AdvancedFetcher”函数和一个“basicFetcher”函数,我在其中任何一个下都收到相同的错误。这个答案建议检查每个错误(我想我有),但我仍然收到错误。谢谢! 编辑#1:

  • 我对std::memory\u order\u acquire和std::memory\u order\u release的理解如下: Acquire意味着在Acquire fence之后出现的内存访问不能重新排序到fence之前。 释放意味着在释放栅栏之前出现的任何内存访问都可以重新排序为栅栏之后。 我不明白的是,为什么在C 11原子库中,获取界限与加载操作相关联,而发布界限与存储操作相关联。