如何使用Gnu编译器在VxWorks7中重载新的/删除运算符



我正在尝试创建一个VxWorks7图像项目(VIP),其中包括我的应用程序,该应用程序重载新的和删除的内容。当我使用应用程序作为可下载内核模块(DKM)单独构建VIP和应用程序时,它通过在目标上启动VIP并使用Workbench4单独下载应用程序DKM来构建和运行良好。然而,如果我试图将VIP和DKM一起构建为一个可引导的VIP,在构建过程中,我会从Workbench中为新的和删除的运算符遇到多个定义错误,如下所示:

C:/BW/Vehicle/builds/cx20X0Up32BitDebugVsb/krnl/gnu_standardlibgnucplus.a(_x_gnu_delaop.o): In function `operator delete[](void*)':
(.text+0x0): multiple definition of `operator delete[](void*)'
C:/BW/Vehicle/builds/Vehicle/cx20X0Up32BitDebugVsb_SANDYBRIDGEgnu/Vehicle_partialImage/Debug/Vehicle_partialImage.o:C:/BW/Alcatraz/Vehicle/src/IRL/Util/heap.cpp:886: first defined here
C:/BW/Vehicle/builds/cx20X0Up32BitDebugVsb/krnl/gnu_standardlibgnucplus.a(_x_gnu_delop.o): In function `operator delete(void*)':
(.text+0x0): multiple definition of `operator delete(void*)'
C:/BW/Vehicle/builds/Vehicle/cx20X0Up32BitDebugVsb_SANDYBRIDGEgnu/Vehicle_partialImage/Debug/Vehicle_partialImage.o:C:/BW/Alcatraz/Vehicle/src/IRL/Util/heap.cpp:841: first defined here
C:/BW/Vehicle/builds/cx20X0Up32BitDebugVsb/krnl/gnu_standardlibgnucplus.a(_x_gnu_newaop.o): In function `operator new[](unsigned int)':
(.text+0x0): multiple definition of `operator new[](unsigned int)'
C:/BW/Vehicle/builds/Vehicle/cx20X0Up32BitDebugVsb_SANDYBRIDGEgnu/Vehicle_partialImage/Debug/Vehicle_partialImage.o:C:/BW/Alcatraz/Vehicle/src/IRL/Util/heap.cpp:813: first defined here
C:/BW/Vehicle/builds/cx20X0Up32BitDebugVsb/krnl/gnu_standardlibgnucplus.a(_x_gnu_newop.o): In function `operator new(unsigned int)':
(.text+0x0): multiple definition of `operator new(unsigned int)'
C:/BW/Alcatraz/Vehicle/builds/Vehicle/cx20X0Up32BitDebugVsb_SANDYBRIDGEgnu/Vehicle_partialImage/Debug/Vehicle_partialImage.o:C:/BW/Alcatraz/Vehicle/src/IRL/Util/heap.cpp:808: first defined here
collect2.exe: error: ld returned 1 exit status 

WindRiver支持提供了在重载new和delete运算符的源文件中进行以下声明的解决方案。这应该是向编译器/链接器发出信号,以省略新/del运算符的库版本。

int ___x_gnu_newaop_o = 1;
int ___x_gnu_newop_o = 1;
int ___x_gnu_delaop_o = 1 ;
int ___x_gnu_delop_o = 1;

这样做,我仍然会得到与上面相同的多重定义错误,WindRiver的支持没有任何可行的建议。有没有人有过在VxWorks7中使用Gnu编译器重载global::new和::delete的经验?

以下是WindRiver Support 66370上的问题链接。不确定它是否具有公共访问权限。

为了调试目的,我重新定义了malloc/free函数,遇到了类似的情况。也许,我的解决方案很粗糙,但它简单高效:我刚刚将标准函数重命名为"malloc_original"one_answers"free_originaal"。因此,所有对malloc和free的调用都只链接到新的实现,而malloc的新版本和free在必要时调用原始功能。方法如下:

  1. 找到具有原始功能的库。在您的情况下,它是libgnucplus.a
  2. 图书馆只是一个有对象的档案馆。用ar -x libgnucplus.a提取
  3. 列出对象中的符号,链接器使用nm objectName.o抱怨(_x_gnu_delaop.o、_x_gnu/delop.o等)。找到运营商的名字,他们会有一些名字篡改
  4. 如果对象除了不需要的运算符之外什么都不导出,并且您不想保留原始实现,那么从除这些之外的所有obj文件创建libgnucplus.a应该是可以的,这样您就可以跳过其他步骤
  5. 否则,运行objcopy --redefine-sym operatorName__WithMangling=operatorNameOriginal__WithMangling objFile.o。我在纯C函数上做过,所以没有篡改,但我确信,篡改不会是一个很大的障碍
  6. 将修改后的obj文件放回lib:ar rvs libgnucplus.a objFile1.o objFile2.o ...
  7. 玩得开心

我不否认,这种方法很肮脏,也有一些缺点。例如,修改后的工具链意味着,它的升级将需要重新执行所有相同的步骤;另一个问题是,开发人员没有意识到这种情况(在长期项目中这种情况并不罕见),很难弄清楚细节。在我的案例中,它用于临时调试内存问题,因此不涉及道德方面:)

事实证明,在尝试Wind River提出的解决方案后,多重定义是由于具有循环引用的库,以及在仅使用某些重载时使用指定所有重载的解决方案。我现在可以使用以下内容构建而不会出现问题,也不需要使用我们以前在VxWorks6.x:中使用的修改后的标准库

// ======== SPECIAL CASE NEW/DELETE OPERATOR OVERLOAD FOR GNU ========
// The following ___x_gnu_????.o global variable definitions are special
// case indicators to Gnu compiler when building the application into an
// integrated VIP (VxWorks Image Project).  They indicate which new and
// delete operators are being overloaded.  Doing this avoids a multiple
// definition build error for new/delete operators.  This multiple
// definition error is only an issue when building application as an
// integrated VIP and not when app is downloaded separate from VIP as a
// Downloadable Kernel Module (DKM).  It is important to only include
// ___x_gnu_????_o variables for the specific operators being
// overloaded.  Defining a ___x_gnu_????_o variable for an operator that
// is not actually overloaded will cause a multiple define error also.
// This solution to overloading new/delete was obtained directly from
// Wind River support and is described in case #66370 and as of this
// date is not described anywhere in Wind River documentation.
// link to case #66370 below. -- 2017Jan18jdn
//
// https://windriver.force.com/support/apex/CaseReadOnly?id=5001600000xKkTYAA0
int ___x_gnu_newaop_o = 1;      // Indicates overload of new [] operator
int ___x_gnu_newop_o = 1;       // Indicates overload of new operator
int ___x_gnu_delaop_o = 1 ;     // Indicates overload of delete [] operator
int ___x_gnu_delop_o = 1;       // Indicates overload of delete operator

最新更新