C++ 使用 extern C 库,意外内存泄漏

问题描述 投票:0回答:2

我创建了一个简单的

C
库,由一个.c和一个.h文件生成。

// test.c
#include "test.h"
#include "stdlib.h"
void GetArray(int * array)
{
  array = (int *) calloc(2, sizeof(int));
  array[0] = 0;
  array[1] = 1;
}
// test.h
void GetArray(int * array);

然后我生成了一个

C++
可执行文件,它将链接到
C
库并调用此函数。

// Test.cpp
#include "Test.hpp"

int main(int argc, char *argv[])
{
  int * array;
  GetArray(array);
  delete[] array;
  return 0;
}

带标题

// Test.hpp
extern "C" {
#include "test.h"
}

为了完整起见,我包含了 Makefile

CC  = gcc
CPP = g++

# ----- C-based library -------
testlib.a: test.o
        ar rcs testlib.a test.o

test.o: test.c
        $(CC) -c $<

# ------ C++ executable that links to C-based library -----
Test: Test.o testlib.a
        $(CPP) Test.o -o $@ testlib.a

Test.o: Test.cpp
        $(CPP) -c $<

.PHONY: clean
clean:
        rm -f *.o Test testlib.a

我惊讶地发现,尽管

delete[] array;
中调用了
Test.cpp
,但 valgrind 泄漏摘要报告显示 8 字节内存肯定丢失了。

我也尝试直接在

array
中创建
Test.cpp
,而不调用 C 库函数
GetArray
。那就是

// Test.cpp
#include "Test.hpp"

int main(int argc, char *argv[])
{
  int * array;
  array = new int[2];
  array[0] = 0;
  array[1] = 1;
  delete[] array;
  return 0;
}

并观察到 valgrind 报告显示没有内存泄漏。我不知道为什么我无法从 C++ 可执行文件中清除在 C 库中定义的函数中分配的内存。

c++ c memory-management memory-leaks extern-c
2个回答
1
投票

更改此:

void GetArray(int * array)
{
  array = (int *) calloc(2, sizeof(int));
  array[0] = 0;
  array[1] = 1;
}

对此:

void GetArray(int** array)
{
  *array = (int *) calloc(2, sizeof(int));
  (*array)[0] = 0;
  (*array)[1] = 1;
}

然后调用如下:

int* array;
GetArray(&array);

否则,如果您只将其声明为

GetArray(int*)
,则参数值
array
将被覆盖,但调用者的数组值永远不会改变。请记住,即使是指针本身也是按值传递的。

更自然的方式当然是这样的:

int* GetArray()
{
  int* array = (int *) calloc(2, sizeof(int));
  array[0] = 0;
  array[1] = 1;
  return array;
}

然后调用为:

int* array = GetArray();

0
投票

要在函数内更改

GetArray
在主ylou中声明的指针数组需要通过引用将其传递给函数。

在 C 中,通过引用传递意味着通过指向对象的指针间接传递对象。因此,取消引用传递给对象的指针将获得对指针指向的对象的直接访问。否则,该函数将创建由传递参数的值初始化的局部变量(参数),并将更改局部变量。用作参数的变量将保持不变。

您可以按以下方式想象您的函数及其调用

GetArray(array);

//...

void GetArray( /*int * patm_array*/)
{
  int *parm_array = array;

  parm_array = (int *) calloc(2, sizeof(int));
  parm_array[0] = 0;
  parm_array[1] = 1;
}

可以看出,函数内更改的是局部变量 parm_array。

所以你需要像这样声明函数

void GetArray( int **array )
{
  *array = (int *) calloc(2, sizeof(int));
  ( *array )[0] = 0;
  ( *array )[1] = 1;
}

并称其为

GetArray( &array );

在 C++ 中,您可以像这样声明和定义函数

void GetArray(int * &array)
{
  array = (int *) calloc(2, sizeof(int));
  array[0] = 0;
  array[1] = 1;
}

并称其为

GetArray( array );
© www.soinside.com 2019 - 2024. All rights reserved.