c++ - Values of a vector are changing when they shouldn't be
问题描述
I am writing a game engine from scratch as a free-time learning exercise. I am currently implementing a rendering queue, but the values of the vector in charge of the queue keep changing. (always to the same value of -107374176 when it should be 10.0f) The vector objRID is of type OBJR*, where OBJR is a struct containing position information, as well as a pointer to a bitmap. The bitmap library I am using doesn't seem to be the culprit, but it can be found at: http://partow.net/programming/bitmap/index.html.
The overarching exception is a read access violation of 0x1CCCCCCCC. I have stepped through the program and have found that the values of the struct change one by one every iteration of the "rep stos" after the 19th iteration. I have no real Idea as to how the "rep stos" could affect something which is seemingly unrelated. (A don't have a great grasp on assembler in the first place) I am very open to suggestions besides the error at hand.
If someone could explain how the following assembly affects the vector objRID I think I would be able to solve this problem myself in the future.
163: int loop()
164: {
00007FF7AC74D580 40 55 push rbp
00007FF7AC74D582 57 push rdi
00007FF7AC74D583 48 81 EC A8 01 00 00 sub rsp,1A8h
00007FF7AC74D58A 48 8D 6C 24 20 lea rbp,[rsp+20h]
00007FF7AC74D58F 48 8B FC mov rdi,rsp
00007FF7AC74D592 B9 6A 00 00 00 mov ecx,6Ah
00007FF7AC74D597 B8 CC CC CC CC mov eax,0CCCCCCCCh
00007FF7AC74D59C F3 AB rep stos dword ptr [rdi] <---- 19th - 26th iteration here
I hate to just throw the whole program in here, but I believe it is much less confusing this way.
The program is structured as such:
#include "stdafx.h"
#include <Windows.h>
#include "bitmap_image.hpp"
#define maxObjects 1024
struct VEC2_f {
float x, y;
VEC2_f(float x, float y)
{
VEC2_f::x = x;
VEC2_f::y = y;
}
VEC2_f()
{
VEC2_f::x = 0.0f;
VEC2_f::y = 0.0f;
}
};
struct OBJR {
VEC2_f pos, vel;
int ID = -1;
bitmap_image* Lbmp;
OBJR(bitmap_image* Lbmp, VEC2_f pos, VEC2_f vel)
{
OBJR::Lbmp = Lbmp;
OBJR::pos = pos;
OBJR::vel = vel;
}
OBJR(bitmap_image* Lbmp, float x, float y, float vx, float vy)
{
OBJR::Lbmp = Lbmp;
OBJR::pos = VEC2_f(x, y);
OBJR::vel = VEC2_f(vx, vy);
}
//if -1 then ID isn't set yet
int getID()
{
return ID;
}
};
std::vector<OBJR*> objRID;
int IDCOUNTER = 0;
bool running = true;
HWND con;
HDC dc;
COLORREF color;
void objInit(OBJR* Lobj)
{
if (objRID.size() > maxObjects)
{
objRID.pop_back();
Lobj->ID = maxObjects; }
Lobj->ID = IDCOUNTER++;
objRID.push_back(Lobj);
}
void input()
{
}
void update()
{
}
VEC2_f interpolate(float interpolation, VEC2_f pos, VEC2_f vel)
{
return VEC2_f(pos.x + (vel.x * interpolation), pos.y + (vel.y * interpolation));
}
void renderBitmap(bitmap_image* Lbmp, VEC2_f Ipos)
{
unsigned int h, w;
rgb_t colorT;
h = Lbmp->height(); <--- Read access violation here
w = Lbmp->width();
for (unsigned int y = 0; y < h; y++)
{
for (unsigned int x = 0; x < w; x++)
{
colorT = Lbmp->get_pixel(x, y);
color = RGB(colorT.red, colorT.green, colorT.blue);
SetPixelV(dc, x + Ipos.x, y + Ipos.y, color);
}
}
}
void renderOBJR(float interpolation, OBJR* obj)
{
renderBitmap(obj->Lbmp, interpolate(interpolation, obj->pos, obj->vel));
}
void render(float interpolation)
{
for (int i = 0; i < objRID.size(); i++)
{
renderOBJR(interpolation, objRID[i]);
}
}
void resizeWindow()
{
RECT r;
GetWindowRect(con, &r);
MoveWindow(con, r.left, r.top, 800, 600, true);
}
int init()
{
con = GetConsoleWindow();
dc = GetDC(con);
resizeWindow();
return 0;
}
int loop()
{ //<--- this is where the disassembly was taken from and is where the Lbmp becomes invalid
const int TPS = 60;
const int SKIP_TICKS = 1000 / TPS;
const int FRAMESKIP = 1;
DWORD next_tick = GetTickCount();
float interpolation;
int loop;
while (running)
{
loop = 0;
while (GetTickCount() > next_tick && loop < FRAMESKIP)
{
input();
update();
next_tick += SKIP_TICKS;
loop++;
}
interpolation = float(GetTickCount() + SKIP_TICKS - next_tick) / float(SKIP_TICKS);
render(interpolation);
}
return 0;
}
int deInit()
{
ReleaseDC(con, dc);
return 0;
}
void test()
{
bitmap_image bitmap = bitmap_image("testBW.bmp");
VEC2_f pos = VEC2_f(10.f, 10.f);
VEC2_f vel = VEC2_f();
OBJR test1 = OBJR(&bitmap, pos, vel);
objInit(&test1);
renderBitmap(&bitmap, pos);
}
int main()
{
init();
test();
loop();
deInit();
return 0;
}
解决方案
rep stosd
是实现 memset 的一种方法。一些编译器会内联它。
看起来您的编译器正在使用它来初始化堆栈内存,其毒性值为0xCCCCCCCC
,4 * 0x6A
字节。(注意它mov rdi, rsp
前面有一个右边。)我假设这是一个调试版本,因为优化的版本不会做额外的工作。
总体异常是 0x1CCCCCCCC 的读取访问冲突。
看起来您从未初始化的对象中读取了一个指针,并且“毒药”值完成了创建一个您可以轻松看到的指针值的工作是虚假的,并且哪些错误而不是默默地继续,直到后来一些错误远离真正的问题.
指针的0x00000001
高半部分是可疑的。也许你部分覆盖了这个对象?在存储指针值的内存上设置一个观察点,并找出还有什么修改它。
或者您在局部变量超出范围后保留指向它们的指针,然后下一个函数调用将堆栈内存重用于其堆栈帧。调试模式代码毒化了它的整个栈帧,覆盖了你的std::vector<OBJR*> objRID;
.
所以改变的不是向量内容或向量对象本身,而是向量内容指向的对象。
同样,0xCCCCCCCC 毒药正在寻找程序中的错误。
(@molbdnilo 发现了这一点。我第一次没有花时间仔细阅读你的整个 C++ 代码。)
推荐阅读
- c# - 从空白空间创建折线单击
- c++ - 如何有效地搜索嵌套映射(C++)中的键?
- php - PHP:为什么在类本身内部静态调用类函数会解析为 __call 而不是 __callStatic?
- php - 使用 Laravel 集体表单和资源控制器进行输入后,如何在另一个页面上显示用户数据?
- python - from lxml import etree ImportError: DLL load failed: 找不到指定的模块
- azure-active-directory - 如何使用 Azure AD+Pingfederate 执行无头身份验证
- python - How to read files in other directory in python
- swift - Alamofire 发送字典数组请求
- node.js - 如何使用带有 Promise 的 Amazon DynamoDB JavaScript SDK
- javascript - 单击 div 内的图标上的事件,该事件也是可单击的