c ++类库动态运行时分配

时间:2016-05-09 11:15:27

标签: c++ runtime size alloc

假设我'有一个接口类

class foo_if_t {

};

,第一个库libfoo_orig.so,其类foo_t继承自foo_if_t并具有以下代码:

#include "foo_if.h"

class foo_t : public foo_if_t{
private:
    int res;
public:
    foo_t(){}
    virtual ~foo_t(){}
};

,第二个库libfoo_mod.so的类foo_t重新定义如下:

#include "foo_if.h"

class foo_t : public foo_if_t{
private:
    int res[100];
public:
    foo_t() {
         for (int i=0; i<100; i++)
         res[i] = i;
    }
    virtual ~foo_t(){}
};

我创建一个符号链接libfoo.so --> libfoo_orig.so并编译以下应用程序

#include "foo_orig.h"

int main(){
    foo_if_t *foo_if = new foo_t();
    delete foo_if;
}

with g++ -ggdb -O0 test.cpp -o test -L. -lfoo(因此链接到libfoo.so)。

此时我将符号链接更改为目标libfoo_mod.so并重新运行代码。这将导致以下错误:

*** Error in `./test': free(): invalid next size (fast): 0x0000000001ec9010 ***
Aborted (core dumped)

我认为可能发生的事情是,来自库foo_t的{​​{1}}的构造函数分配占用的堆大于foo_orig.so的堆,所以当{{1}时调用foo_mod.so构造函数,它会使堆内存超出分配边界(因此会破坏堆foo_mod.so块引用)。这告诉我堆预留在链接时以某种方式预先计算,而我认为它将在运行时根据调用的实际构造函数动态解析。我错了,如果没有,为什么生成的输出代码表现得像这样?

作为反证明测试,我在为每个库编写的foo_t实现中包装next调用;从主代码调用new foo_t()可以正常工作。

1 个答案:

答案 0 :(得分:2)

这里的问题是你的库代码和主程序代码对foo_t的布局结构有不同的看法。尽管它们都识别出类型的存在,但它们都使用不同版本的头文件进行编译来定义它。这总会导致大麻烦。

在您的情况下,问题是由new执行的实际内存分配是从主程序编译的,因此可以了解创建的对象的大小。同时,构造函数使用库代码进行编译,并且对底层对象大小有完全不同的概念。因此,主程序在堆上创建一个sizeof(foo_t)的对象 - 从它的角度来看是sizeof(int)。构造函数,不知道这一点,愉快地使内存高达100英寸,从而破坏了堆。

基本上你不能欺骗&#39;通过这种方式。如果你改变头文件,你应该总是重新编译依赖于这个头的库,或者面对这样的不可预测的麻烦(显然你在这种情况下故意这样做,但这也很容易在意外完成)。