C++ sizeof(*此)给出了错误的值
我有一个类,C.C有一个成员变量声明为:bool markerStart 在C中,对sizeof(*this)的调用给出了0x216字节的值 在C中的其他地方,我会这样做:markerStart=false 这个调用并没有将markerStart设置为false,实际上是在破坏内存中下一个类的开始 查看反汇编代码,我发现:C++ sizeof(*此)给出了错误的值,c++,assembly,sizeof,C++,Assembly,Sizeof,我有一个类,C.C有一个成员变量声明为:bool markerStart 在C中,对sizeof(*this)的调用给出了0x216字节的值 在C中的其他地方,我会这样做:markerStart=false 这个调用并没有将markerStart设置为false,实际上是在破坏内存中下一个类的开始 查看反汇编代码,我发现: markerStart = false; 06FB6B7F mov eax, dword ptr [this] 06FB6B78 mov
markerStart = false;
06FB6B7F mov eax, dword ptr [this]
06FB6B78 mov byte ptr [eax+218h], 0
第二条move指令将+0x218处的一个字节设置为零,但由于该类的长度只有0x216字节,因此这是在破坏内存
作为对注释的响应,它肯定是markerStart=false指令。我可以在反汇编程序视图和内存视图中观察它的发生(并使用Windbg,通过使用数据断点)。下一个类的第一个字节被设置为零,这会弄乱它的vftbl指针
注意:取markerStart的地址并从中减去它,得到0x211
有谁能告诉我从哪里着手解决这个问题的线索吗
更新:谢谢你的帮助。
如果没有代码,你们几乎不可能解决这个问题。我想要的是关于从哪里开始寻找的提示。你们大多数人都提供了很好的提示,所以谢谢你们
我终于找到了问题所在。在这种情况下,对齐已在一个类中设置,并且在关键代码块之后未正确重置。对齐错误的类恰好在声明类C之前被编译,因此问题就出现了。该类可能只有0x216字节,但下一个对象当然是第一个对象开始后的0x218字节。您的对象显然是按4字节内存边界对齐的,这是默认值
你必须到别处去寻找你的记忆在哪里被破坏。这绝对不是“markerStart=false”指令。您需要发布更多代码——如果您可以将其删减到发生异常的最小类定义,那就更好了。这本身可能会帮助你确定发生了什么 我想到的一些可能性:
如果没有更多的信息,我会选择违反ODR。这些可能是隐蔽的,在编译或链接时无法检测到 这可能是“类切片”问题的一个实例吗?您的类是否有虚拟方法?或者它是从具有虚拟方法的类派生的?或者你的类有多重继承
答案取决于您使用的编译器,编译器可以存储指向虚拟表的指针。这确实是一个实现细节,但只要它与标准一样工作,它就可以用每个对象存储任何类型的数据。代码中没有一些奇怪的指针转换问题吗?类似的东西
struct A
{
int i;
};
struct B : public A
{
int j;
void f() { j=0; }
};
int main()
{
A x;
A* p=&x;
((B*)p)->f();
return 0;
}
你能不能检查一下,它实际上指向了一个C的实例,在这一行中,它正在破坏你的记忆?您是否可以在此时打印
typeid(*this).name()
(假设类具有一些虚拟函数)?您遇到的问题可能是由于某些依赖项错误,而不是编译器的任何错误(成百上千的开发人员都在使用编译器,如果有这样的问题,现在就已经发现了)
考虑一个包含以下两个文件的简单项目。文件a.cpp:
class C
{
public:
C () : m_value (42) { }
void Print () { cout << "C::m_value = " << m_value << endl; }
private:
int m_value;
};
void DoSomethingWithC (C &c);
void main (void)
{
C array_of_c [2];
DoSomethingWithC (array_of_c [0]);
array_of_c [0].Print ();
array_of_c [1].Print ();
}
如果编译上述两个文件并链接它们,则不会得到任何错误或警告。但是,当您运行应用程序时,您会发现DoSomethingWithC clobbers array_of_c[1],即使其参数是array_of_c[0]
因此,您的问题可能是一个源文件以一种方式查看类,而另一个文件以另一种方式查看类。如果依赖性检查失败,可能会发生这种情况
尝试强制全部重建。如果这样做有效,那么您需要了解依赖项失败的原因(例如,DevStudio有时会出错).正如Pontus所指出的,您可能以某种方式打破了“一个定义”规则。您可能已将带有C类定义的头文件包含在两个翻译单元中,其中其他代码(通常在前面的头文件中)更改了C类定义的解释方式,从而使其在两个翻译单元中具有不同的大小尼茨
一种可能性是,您不小心更改了默认成员对齐方式(通过编译器的命令行参数或通过源代码中的#pragma),因此两个不同的翻译单元认为由于填充量不同,结构的大小不同(大多数x86编译器默认在4字节边界上对齐,但允许您根据需要请求在1字节边界上对齐)。在其他头文件中查找一个#pragma,更改缺少以下#prama的默认对齐,以将其恢复到以前的值(您没有指定哪个编译器,因此我无法给出详细信息).最近您的类定义或项目设置有任何更改吗?我看到过类似的问题,我遇到过这样的荒谬行为,原因是链接了过时的对象文件。对象文件不再与源文件匹配。请尝试干净完整的重建。检查*这是否真的指向t他开始上课,而不是通过一个坏指针来调用。< /p>发布一些实际的C++代码来说明问题,你能发布一些实际的代码吗?C的定义可能是一个很好的开始,可能是因为218!= 0x218 [EAX+2]是一个类型,一个
class C
{
public:
int a,b;
};
void DoSomethingWithC (C &c)
{
c.b = 666;
}