- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在为内存非常有限的 NIOS II 内核编译 C++ 程序。由于它是一个嵌入式系统,我们也不使用堆。由于我们将继承添加到我们的代码中,我们看到 malloc 和 free(以及相关函数)被构建到我们的二进制文件中,从而增加了它的大小千字节。
我们有一个纯虚基类 StatisticsApi 和一个派生类 Statistics。统计数据,它们都定义了虚拟析构函数。
我们正在使用带有 fno-rtti 和 -fno_expections 的 Alteras GCC 进行编译,并且还定义了我们自己的 __cxa_pure_virtual()
。
仔细观察我们发现 delete 是从析构函数中调用的(因此是免费的)。这是为什么?它试图释放什么内存?
这里是析构函数的汇编器:
0000c6b8 <_ZN7Namespace12StatisticsD0Ev>:
c6b8: defffd04 addi sp,sp,-12
c6bc: dfc00215 stw ra,8(sp)
c6c0: df000115 stw fp,4(sp)
c6c4: df000104 addi fp,sp,4
c6c8: e13fff15 stw r4,-4(fp)
c6cc: 00c000b4 movhi r3,2
c6d0: 18c74b04 addi r3,r3,7468
c6d4: e0bfff17 ldw r2,-4(fp)
c6d8: 10c00015 stw r3,0(r2)
c6dc: e13fff17 ldw r4,-4(fp)
c6e0: 000c7f00 call c7f0 <_ZN7Namespace15StatisticsApiD2Ev>
c6e4: 00800044 movi r2,1
c6e8: 10803fcc andi r2,r2,255
c6ec: 1005003a cmpeq r2,r2,zero
c6f0: 1000021e bne r2,zero,c6fc <_ZN7LinCtrl12TxStatisticsD0Ev+0x44>
c6f4: e13fff17 ldw r4,-4(fp)
c6f8: 000c8e00 call c8e0 <_ZdlPv>
c6fc: e037883a mov sp,fp
c700: dfc00117 ldw ra,4(sp)
c704: df000017 ldw fp,0(sp)
c708: dec00204 addi sp,sp,8
c70c: f800283a ret
0000c710 <_ZN7Namespace12StatisticsD1Ev>:
c710: defffd04 addi sp,sp,-12
c714: dfc00215 stw ra,8(sp)
c718: df000115 stw fp,4(sp)
c71c: df000104 addi fp,sp,4
c720: e13fff15 stw r4,-4(fp)
c724: 00c000b4 movhi r3,2
c728: 18c74b04 addi r3,r3,7468
c72c: e0bfff17 ldw r2,-4(fp)
c730: 10c00015 stw r3,0(r2)
c734: e13fff17 ldw r4,-4(fp)
c738: 000c7f00 call c7f0 <_ZN7Namespace15StatisticsApiD2Ev>
c73c: 0005883a mov r2,zero
c740: 10803fcc andi r2,r2,255
c744: 1005003a cmpeq r2,r2,zero
c748: 1000021e bne r2,zero,c754 <_ZN7Namespace12StatisticsD1Ev+0x44>
c74c: e13fff17 ldw r4,-4(fp)
c750: 000c8e00 call c8e0 <_ZdlPv>
c754: e037883a mov sp,fp
c758: dfc00117 ldw ra,4(sp)
c75c: df000017 ldw fp,0(sp)
c760: dec00204 addi sp,sp,8
c764: f800283a ret
0000c768 <_ZN7Namespace12StatisticsD2Ev>:
c768: defffd04 addi sp,sp,-12
c76c: dfc00215 stw ra,8(sp)
c770: df000115 stw fp,4(sp)
c774: df000104 addi fp,sp,4
c778: e13fff15 stw r4,-4(fp)
c77c: 00c000b4 movhi r3,2
c780: 18c74b04 addi r3,r3,7468
c784: e0bfff17 ldw r2,-4(fp)
c788: 10c00015 stw r3,0(r2)
c78c: e13fff17 ldw r4,-4(fp)
c790: 000c7f00 call c7f0 <_ZN7Namespace15StatisticsApiD2Ev>
c794: 0005883a mov r2,zero
c798: 10803fcc andi r2,r2,255
c79c: 1005003a cmpeq r2,r2,zero
c7a0: 1000021e bne r2,zero,c7ac <_ZN7Namespace12StatisticsD2Ev+0x44>
c7a4: e13fff17 ldw r4,-4(fp)
c7a8: 000c8e00 call c8e0 <_ZdlPv>
c7ac: e037883a mov sp,fp
c7b0: dfc00117 ldw ra,4(sp)
c7b4: df000017 ldw fp,0(sp)
c7b8: dec00204 addi sp,sp,8
c7bc: f800283a ret
下面是基类的析构函数:
0000c7f0 <_ZN7Namespace15StatisticsApiD2Ev>:
c7f0: defffd04 addi sp,sp,-12
c7f4: dfc00215 stw ra,8(sp)
c7f8: df000115 stw fp,4(sp)
c7fc: df000104 addi fp,sp,4
c800: e13fff15 stw r4,-4(fp)
c804: 00c000b4 movhi r3,2
c808: 18c76204 addi r3,r3,7560
c80c: e0bfff17 ldw r2,-4(fp)
c810: 10c00015 stw r3,0(r2)
c814: 0005883a mov r2,zero
c818: 10803fcc andi r2,r2,255
c81c: 1005003a cmpeq r2,r2,zero
c820: 1000021e bne r2,zero,c82c <_ZN7Namespace15StatisticsApiD2Ev+0x3c>
c824: e13fff17 ldw r4,-4(fp)
c828: 000c8e00 call c8e0 <_ZdlPv>
c82c: e037883a mov sp,fp
c830: dfc00117 ldw ra,4(sp)
c834: df000017 ldw fp,0(sp)
c838: dec00204 addi sp,sp,8
c83c: f800283a ret
0000c840 <_ZN7LinCtrl15TxStatisticsApiD0Ev>:
c840: defffd04 addi sp,sp,-12
c844: dfc00215 stw ra,8(sp)
c848: df000115 stw fp,4(sp)
c84c: df000104 addi fp,sp,4
c850: e13fff15 stw r4,-4(fp)
c854: 00c000b4 movhi r3,2
c858: 18c76204 addi r3,r3,7560
c85c: e0bfff17 ldw r2,-4(fp)
c860: 10c00015 stw r3,0(r2)
c864: 00800044 movi r2,1
c868: 10803fcc andi r2,r2,255
c86c: 1005003a cmpeq r2,r2,zero
c870: 1000021e bne r2,zero,c87c <_ZN7Namespace15StatisticsApiD0Ev+0x3c>
c874: e13fff17 ldw r4,-4(fp)
c878: 000c8e00 call c8e0 <_ZdlPv>
c87c: e037883a mov sp,fp
c880: dfc00117 ldw ra,4(sp)
c884: df000017 ldw fp,0(sp)
c888: dec00204 addi sp,sp,8
c88c: f800283a ret
0000c890 <_ZN7Namespace15StatisticsApiD1Ev>:
c890: defffd04 addi sp,sp,-12
c894: dfc00215 stw ra,8(sp)
c898: df000115 stw fp,4(sp)
c89c: df000104 addi fp,sp,4
c8a0: e13fff15 stw r4,-4(fp)
c8a4: 00c000b4 movhi r3,2
c8a8: 18c76204 addi r3,r3,7560
c8ac: e0bfff17 ldw r2,-4(fp)
c8b0: 10c00015 stw r3,0(r2)
c8b4: 0005883a mov r2,zero
c8b8: 10803fcc andi r2,r2,255
c8bc: 1005003a cmpeq r2,r2,zero
c8c0: 1000021e bne r2,zero,c8cc <_ZN7Namespace15StatisticsApiD1Ev+0x3c>
c8c4: e13fff17 ldw r4,-4(fp)
c8c8: 000c8e00 call c8e0 <_ZdlPv>
c8cc: e037883a mov sp,fp
c8d0: dfc00117 ldw ra,4(sp)
c8d4: df000017 ldw fp,0(sp)
c8d8: dec00204 addi sp,sp,8
c8dc: f800283a ret
最后删除:
0000c8e0 <_ZdlPv>:
c8e0: 20000126 beq r4,zero,c8e8 <_ZdlPv+0x8>
c8e4: 000ebf01 jmpi ebf0 <free>
c8e8: f800283a ret
这里是 NIOS II 指令集的链接以供引用:http://www.altera.com/literature/hb/nios2/n2cpu_nii51017.pdf
我们找到的两个解决方案/解决方法是:
将 new/delete 重新定义为空函数(没有堆,所以它们不应该无论如何都会被调用!)从而避免调用 free。
在 C++ 中保留未定义的析构函数,这使得它们无法获取在汇编程序中实例化。虽然编译器会提示没有虚拟析构函数。
解决方法与否,为什么析构函数调用免费?它试图释放什么内存!?!我们还有其他既不用于基类也不用于派生类的析构函数,它们不调用 free。这是这样一个析构函数的样子:
00005194 <_ZN7Namespace16OtherClassD2Ev>:
5194: defffe04 addi sp,sp,-8
5198: df000115 stw fp,4(sp)
519c: df000104 addi fp,sp,4
51a0: e13fff15 stw r4,-4(fp)
51a4: e037883a mov sp,fp
51a8: df000017 ldw fp,0(sp)
51ac: dec00104 addi sp,sp,4
51b0: f800283a ret
000051b4 <_ZN7Namespace16OtherClassD1Ev>:
51b4: defffe04 addi sp,sp,-8
51b8: df000115 stw fp,4(sp)
51bc: df000104 addi fp,sp,4
51c0: e13fff15 stw r4,-4(fp)
51c4: e037883a mov sp,fp
51c8: df000017 ldw fp,0(sp)
51cc: dec00104 addi sp,sp,4
51d0: f800283a ret
而且,一般来说,为什么每个析构函数(D0、D1 和 D2)都有多个函数?
最佳答案
当您使用虚拟析构函数对对象调用 delete 时,它会在虚拟表中查找要调用的函数。该函数调用析构函数并释放内存,因为只有在派生级别它才知道传递给自由函数的正确指针。
问题在于编译器不知道您从未调用 delete。它仍然必须创建代码,即使它可能永远不会被使用,就像任何其他虚函数一样。
尽管作为一般规则,析构函数在具有其他虚函数的类中应该是虚的,但这可能是一个有效的异常(exception)。使析构函数在基类中受到保护将有助于避免错误。
关于c++ - 为什么基类析构函数调用免费,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25745983/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!