I have the following class structure in IAR:
class A
{
public:
A(){}
virtual ~A() {};
virtual void load() {};
};
class C
{
public:
C()
{
}
};
class D;
class B : public A
{
public:
B() : invert(false) {};
virtual ~B() {};
void load()
{
}
private:
C member_c;
std::vector<D*> vector_of_d;
struct {
bool var_1:1;
bool var_2:1;
bool var_3:1;
bool var_4:1;
bool invert:1;
};
};
I ran into errors with the assembly generated to initialize B, where it seems to be "confused" about where the VTable pointer is located where the anonymous bit field of the structure is located. When it goes to set the inverted bit to false, it jumps to the first word of the object (which is a VTable pointer) and flips the bit to the address. When I call later load(), it follows an invalid VTable pointer and finishes looking for a null pointer, which then blindly follows. Things obviously fall apart from there.
Here is sample code that will cause this problem:
void load_A(A* to_be_loaded){
if(to_be_loaded) to_be_loaded->load();
}
int main(){
load_A(new B());
}
: - undefined? , GCC-ARM, , IAR. :
, . , , IAR, GCC. IAR .
, B
1 | B() : invert(false) {};
2 |B::B():
3 |_ZN6BC1Ev:
4 | 0x80645e8: 0xb510 PUSH {R4, LR}
5 | 0x80645ea: 0x4604 MOV R4, R0
6 | B() : invert(false) {};
7 | 0x80645ec: 0xf007 0xfb20 BL A::subobject A() ; 0x806bc30
8 | 0x80645f0: 0x4807 LDR.N R0, [PC,
9 | 0x80645f2: 0x6020 STR R0, [R4]
10| 0x80645f4: 0xf104 0x0018 ADD.W R0, R4,
11| 0x80645f8: 0xf00a 0xfadd BL C::C() ; 0x806ebb6
12| 0x80645fc: 0xf104 0x001c ADD.W R0, R4,
13| 0x8064600: 0xf00e 0xff2e BL std::vector<D *>::vector() ; 0x8073460
14| 0x8064604: 0x7820 LDRB R0, [R4]
15| 0x8064606: 0xf000 0x00ef AND.W R0, R0, #239 ; 0xef
16| 0x806460a: 0x7020 STRB R0, [R4]
17| B() : invert(false) {};
18| 0x806460c: 0x4620 MOV R0, R4
19| 0x806460e: 0xbd10 POP {R4, PC}
20| 0x8064610: 0x08088808 DC32 0x8088808 (134776840)
14 , R4, . , , , , VTable. , 15, , 16.
, B, ( ), :
class B : public A
{
public:
B(){ invert = false; };
virtual ~B() {};
void load()
{
}
private:
C member_c;
std::vector<D*> vector_of_d;
struct {
bool var_1:1;
bool var_2:1;
bool var_3:1;
bool var_4:1;
bool invert:1;
}
};
: , LDRB STRB 14 16. .
1 | B(){ invert = false; };
2 |B::B():
3 |_ZN6BC1Ev:
4 | 0x80645e8: 0xb510 PUSH {R4, LR}
5 | 0x80645ea: 0x4604 MOV R4, R0
6 | B(){ invert = false; };
7 | 0x80645ec: 0xf007 0xfb20 BL A::subobject A() ; 0x806bc30
8 | 0x80645f0: 0x4807 LDR.N R0, [PC,
9 | 0x80645f2: 0x6020 STR R0, [R4]
10| 0x80645f4: 0xf104 0x0018 ADD.W R0, R4,
11| 0x80645f8: 0xf00a 0xfadd BL C::C() ; 0x806ebb6
12| 0x80645fc: 0xf104 0x001c ADD.W R0, R4,
13| 0x8064600: 0xf00e 0xff2e BL std::vector<D *>::vector() ; 0x8073460
14| 0x8064604: 0x7820 LDRB R0, [R4,
15| 0x8064606: 0xf000 0x00ef AND.W R0, R0, #239 ; 0xef
16| 0x806460a: 0x7020 STRB R0, [R4,
17| B(){ invert = false; };
18| 0x806460c: 0x4620 MOV R0, R4
19| 0x806460e: 0xbd10 POP {R4, PC}
20| 0x8064610: 0x08088808 DC32 0x8088808 (134776840)
: 8 , , , - .
- , ?