如何使用 Gnu 编译器在 VxWorks 7 中重载 new/delete 运算符
How to overload new/delete operators in VxWorks 7 with Gnu compiler
我正在尝试创建一个 VxWorks7 图像项目 (VIP),其中包括我的应用程序,它重载了 new 和 delete。当我使用应用程序作为可下载内核模块 (DKM) 单独构建 VIP 和应用程序时,它通过在目标上启动 VIP 并使用 Workbench4 单独下载应用程序 DKM 来构建和运行良好。但是,如果我尝试将 VIP 和 DKM 一起构建为单个可启动 VIP,我会在构建过程中从 Workbench 得到多个新操作符和删除操作符的定义错误,如下所示:
C:/BW/Vehicle/builds/cx20X0Up32BitDebugVsb/krnl/gnu_standard\libgnucplus.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_standard\libgnucplus.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_standard\libgnucplus.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_standard\libgnucplus.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 运算符的源文件中进行以下声明的解决方案。这应该表示 compiler/linker 省略 new/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 支持没有任何可行的建议。有没有人有过使用 Gnu 编译器在 VxWorks7 中重载 global ::new 和 ::delete 的经验?
这里是 link WindRiver 支持 66370 上的问题。不确定它是否具有 public 访问权限。
我 运行 遇到过类似情况,重新定义 malloc/free 函数用于调试目的。也许,我的解决方案很粗糙,但它简单高效:我只是将标准函数重命名为 "malloc_original" 和 "free_original"。因此,所有对 malloc 和 free 的调用都只链接到新的实现,而新版本的 malloc 和 free 会在必要时调用原始功能。方法如下:
- 找到具有原始功能的库。在你的情况下它 libgnucplus.a
- 图书馆只是一个带有对象的档案。使用
ar -x libgnucplus.a
提取它们
- 列出对象中的符号,链接器抱怨(_x_gnu_delaop.o、_x_gnu_delop.o 等)使用
nm objectName.o
。找到运营商的名字,他们会有一些name mangling
- 如果对象除了不需要的运算符外什么都不导出,并且您不想保留原始实现,则可以从除这些之外的所有 obj 文件创建 libgnucplus.a,这样您就可以跳过其他步骤
- 否则运行
objcopy --redefine-sym operatorName__WithMangling=operatorNameOriginal__WithMangling objFile.o
。我是在纯 C 函数上做的,所以没有修改,但我敢肯定,修改不会是一个很大的障碍。
- 将修改后的obj文件放回lib中:
ar rvs libgnucplus.a objFile1.o objFile2.o ...
- 玩得开心
我不否认,这种方法很脏而且有一些缺点。例如,修改后的工具链意味着,其升级将需要 re-doing 所有相同的步骤;另一个是开发人员不知道这种情况(这在长期项目中并不罕见)将很难弄清楚细节。在我的例子中,它用于临时调试内存问题,所以不涉及道德方面:)
事实证明,在尝试 Wind River 提议的解决方法后出现多重定义是由于库具有循环引用,并且还由于使用解决方法指定了所有重载而仅使用了一些重载。我现在可以使用以下方法构建而不会出现问题,并且无需求助于我们之前在 VxWorks 6.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
我正在尝试创建一个 VxWorks7 图像项目 (VIP),其中包括我的应用程序,它重载了 new 和 delete。当我使用应用程序作为可下载内核模块 (DKM) 单独构建 VIP 和应用程序时,它通过在目标上启动 VIP 并使用 Workbench4 单独下载应用程序 DKM 来构建和运行良好。但是,如果我尝试将 VIP 和 DKM 一起构建为单个可启动 VIP,我会在构建过程中从 Workbench 得到多个新操作符和删除操作符的定义错误,如下所示:
C:/BW/Vehicle/builds/cx20X0Up32BitDebugVsb/krnl/gnu_standard\libgnucplus.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_standard\libgnucplus.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_standard\libgnucplus.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_standard\libgnucplus.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 运算符的源文件中进行以下声明的解决方案。这应该表示 compiler/linker 省略 new/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 支持没有任何可行的建议。有没有人有过使用 Gnu 编译器在 VxWorks7 中重载 global ::new 和 ::delete 的经验?
这里是 link WindRiver 支持 66370 上的问题。不确定它是否具有 public 访问权限。
我 运行 遇到过类似情况,重新定义 malloc/free 函数用于调试目的。也许,我的解决方案很粗糙,但它简单高效:我只是将标准函数重命名为 "malloc_original" 和 "free_original"。因此,所有对 malloc 和 free 的调用都只链接到新的实现,而新版本的 malloc 和 free 会在必要时调用原始功能。方法如下:
- 找到具有原始功能的库。在你的情况下它 libgnucplus.a
- 图书馆只是一个带有对象的档案。使用
ar -x libgnucplus.a
提取它们
- 列出对象中的符号,链接器抱怨(_x_gnu_delaop.o、_x_gnu_delop.o 等)使用
nm objectName.o
。找到运营商的名字,他们会有一些name mangling - 如果对象除了不需要的运算符外什么都不导出,并且您不想保留原始实现,则可以从除这些之外的所有 obj 文件创建 libgnucplus.a,这样您就可以跳过其他步骤
- 否则运行
objcopy --redefine-sym operatorName__WithMangling=operatorNameOriginal__WithMangling objFile.o
。我是在纯 C 函数上做的,所以没有修改,但我敢肯定,修改不会是一个很大的障碍。 - 将修改后的obj文件放回lib中:
ar rvs libgnucplus.a objFile1.o objFile2.o ...
- 玩得开心
我不否认,这种方法很脏而且有一些缺点。例如,修改后的工具链意味着,其升级将需要 re-doing 所有相同的步骤;另一个是开发人员不知道这种情况(这在长期项目中并不罕见)将很难弄清楚细节。在我的例子中,它用于临时调试内存问题,所以不涉及道德方面:)
事实证明,在尝试 Wind River 提议的解决方法后出现多重定义是由于库具有循环引用,并且还由于使用解决方法指定了所有重载而仅使用了一些重载。我现在可以使用以下方法构建而不会出现问题,并且无需求助于我们之前在 VxWorks 6.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