2

----------------------------------------------1-------- ----------------------------------

我正在为运行嵌入式 Linux 的 ARM 编译程序。我本来是把程序写成c++程序的,所以代码中有一些operator newoperator deletes。现在,要为典型的 PC 平台编译带有operator news 和operator deletes 的东西,我需要为链接器指定一个特定的参数 (-lstdc++)。我不知道这到底是做什么的。

现在,如果我尝试将此链接器选项与我的 ARM 交叉编译器一起使用,我会正确链接,但在运行时会失败并显示以下消息:

ld.so 检测到不一致:dl-deps.c:622:_dl_map_object_deps:断言“nlist > 1”失败!

如果我省略链接选项,我运行良好。这看起来像是一个断言失败,但这是我愿意冒险猜测的。任何人都可以阐明这个错误或其可能的原因吗?

-----------------------------------------------------------2-- ----------------------------------

我决定省略 (-lstdc++) 选项,并将我的所有类指针替换为指向堆栈上变量实例的指针。这行得通,但它显然是草率的,因为这应该是学生的一个例子,我希望它干净。一个干净的方法是创建我自己的operator newand operator delete...但我将如何实际使用自定义运算符并不明显。

举个例子,someClass * foo = new someClass(arg);这是三个(?)步骤。

  1. 调用运算符 new。为新的类实例分配一些内存。
  2. 调用类构造函数。
  3. 将类实例放入由 operator new 创建的内存位置

我不知道这些步骤的顺序。我不知道如何独立于在堆栈上创建该类型的新变量来调用类构造函数。而且我不知道如何将新的类变量从它开始的地方放入堆中。

4

1 回答 1

1

首先,修正。您上面的创建语句是两步,而不是三步;类构造函数直接应用于分配的内存区域,以将其从“随机内存”转换为对象实例。不过,否则是对的。

重载 operator new 相对简单。您不必在 operator new 中调用类构造函数;该语言分别处理这些步骤。运算符 new() 本质上只是 C++ 的 malloc() 版本:

void *operator new(std::size_t sz) {
    void *out = ::malloc(sz);
    if (!out) throw new std::bad_alloc();
    return out;
}

以上基本模仿了真实的操作符new。您需要对其进行调整以执行使您的代码支持 ARM 所需的任何特殊操作。不过这里有一些魔法,所以要小心。在 operator new() 结束后,该语言会调用您的类构造函数,它可以自由地除外。如果是这样,则需要 C++ 释放由 operator new() 分配的内存(因为程序员没有对它的引用,因此不能自己释放它)。因此,C++ 将在这种情况下神奇地触发 operator delete() ......但前提是它可以找到完美匹配的版本。

TL;DR:如果您重载 operator new(),请始终重载 operator delete(),并确保它们在签名、范围等方面匹配。

于 2012-10-10T02:06:12.643 回答