You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SWIG教程中Python列表转char**示例触发malloc错误求助

Fixing Malloc Error When Converting Python List to char** with SWIG on macOS

Let's break down what's happening here and how to fix it:

First, that malloc error (pointer being freed was not allocated) almost always means there's a mismatch in memory management: your code is trying to free memory that wasn't allocated with malloc (or was already freed). In this case, it's likely the SWIG-generated code is attempting to release Python-managed string pointers instead of memory explicitly allocated for the C++ side.

Why This Happens

The default SWIG typemap for converting Python lists to char** might be directly passing pointers to Python's internal string storage (which Python manages) instead of creating copies of the strings in heap memory allocated via malloc. When SWIG tries to free those pointers later, it hits the error because that memory wasn't allocated by the C runtime.

Step-by-Step Fix

1. Update Your SWIG Interface File (example.i)

Replace your existing interface code with this, which explicitly handles memory allocation and cleanup correctly:

%module example

%{
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
%}

// Typemap to convert Python list to char** (with proper memory allocation)
%typemap(in) char ** {
    if (!PyList_Check($input)) {
        PyErr_SetString(PyExc_TypeError, "Input must be a list of strings");
        return NULL;
    }

    int list_size = PyList_Size($input);
    // Allocate array of char pointers (plus NULL terminator)
    $1 = (char**)malloc((list_size + 1) * sizeof(char*));
    if (!$1) {
        PyErr_SetString(PyExc_MemoryError, "Failed to allocate memory for argument array");
        return NULL;
    }

    for (int i = 0; i < list_size; i++) {
        PyObject* item = PyList_GetItem($input, i);
        if (!PyUnicode_Check(item)) {
            // Clean up already allocated memory on error
            for (int j = 0; j < i; j++) free($1[j]);
            free($1);
            PyErr_SetString(PyExc_TypeError, "All list items must be strings");
            return NULL;
        }

        const char* py_str = PyUnicode_AsUTF8(item);
        // Allocate memory for the string copy
        $1[i] = (char*)malloc(strlen(py_str) + 1);
        if (!$1[i]) {
            // Cleanup on failure
            for (int j = 0; j < i; j++) free($1[j]);
            free($1);
            PyErr_SetString(PyExc_MemoryError, "Failed to allocate memory for string");
            return NULL;
        }
        strcpy($1[i], py_str);
    }
    $1[list_size] = NULL; // Null-terminate the array for C-style handling
}

// Typemap to free the allocated char** after function call
%typemap(freearg) char ** {
    if ($1) {
        for (int i = 0; $1[i]; i++) {
            free($1[i]);
        }
        free($1);
    }
}

// Your target function declaration
%inline %{
void print_args(char** args) {
    for (int i = 0; args[i]; i++) {
        printf("Argument %d: %s\n", i, args[i]);
    }
}
%}

2. Clean Up Your setup.py

Fix the commented-out Extension configuration to ensure all source files are included properly:

#!/usr/bin/env python
""" setup.py file for SWIG example """
from distutils.core import setup, Extension
import os
import glob

# gather up all the source files
srcFiles = ['example.i']
includeDirs = []
srcDir = os.path.abspath('src')
for root, dirnames, filenames in os.walk(srcDir):
    for dirname in dirnames:
        absPath = os.path.join(root, dirname)
        globStr = "%s/*.c*" % absPath
        files = glob.glob(globStr)
        includeDirs.append(absPath)
        srcFiles += files

extra_args = ['-stdlib=libc++', '-mmacosx-version-min=10.7', '-std=c++17', '-fno-rtti']
os.environ["CC"] = 'clang++'

# Properly define the extension module
example_module = Extension(
    '_example',
    srcFiles,
    include_dirs=includeDirs,
    swig_opts=['-c++'],
    extra_compile_args=extra_args,
)

setup(
    name='example',
    version='0.1',
    author="SWIG Docs",
    description="""Simple swig example from docs""",
    ext_modules=[example_module],
    py_modules=["example"],
)

3. Recompile and Test

Run these commands to rebuild the extension:

# Clean previous builds (optional but recommended)
rm -rf build _example.so example.py example_wrap.cxx

# Build the extension
python setup.py build_ext --inplace

Now test again:

import example
example.print_args(["a","bc","dc"])

This should work without the malloc error, as we're now explicitly copying each string into malloc-allocated memory, then properly freeing that memory after the function call.

内容的提问来源于stack exchange,提问作者Guillaume

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 07:12:35