实现IK时触发read access violation错误(this为0xFFFFFFFFFFFFFFF7)
解决逆向运动学IK实现中的read access violation错误
你遇到的read access violation错误(提示this值为0xFFFFFFFFFFFFFFF7),核心原因是**std::vector扩容导致父指针失效**,而非单纯的指针引用理解问题。
问题根源分析
std::vector在调用push_back时,如果当前存储容量不足,会自动重新分配一块更大的内存空间,将旧元素拷贝到新内存后释放旧空间。你在循环中创建Segment时,传入的&segments[i-1]是旧内存中的地址,当vector扩容后,这个地址指向的内存已经被释放,变成了野指针。调用drag方法时通过野指针访问父节点,直接触发了内存访问错误。
解决方案
方案1:提前预留vector容量
在循环前调用reserve方法,让vector一次性分配足够的内存,避免后续扩容导致指针失效。
修改后的main函数代码:
int main() { std::vector<Segment> segments; size_t segment_amt = 10; int length = 0; segments.reserve(segment_amt); // 提前预留足够容量,避免扩容 for (int i = 0; i < segment_amt; i++) { if (i == 0) { segments.push_back(Segment(0.0f, 0.0f, length, 0.0f)); } else { segments.push_back(Segment(segments[i - 1].getStart().x, segments[i - 1].getStart().y, length, 0.0f, &segments[i - 1])); } } Segment& endSeg = segments[segments.size() - 1]; endSeg.drag(0, 0); // 正常执行 }
方案2:使用堆分配指针容器
改用std::vector<std::unique_ptr<Segment>>存储对象,每个Segment在堆上分配内存,地址不会因vector扩容而改变,父指针始终有效。
修改后的代码示例:
int main() { std::vector<std::unique_ptr<Segment>> segments; size_t segment_amt = 10; int length = 0; for (int i = 0; i < segment_amt; i++) { if (i == 0) { segments.push_back(std::make_unique<Segment>(0.0f, 0.0f, length, 0.0f)); } else { auto& prevSeg = segments[i-1]; segments.push_back(std::make_unique<Segment>( prevSeg->getStart().x, prevSeg->getStart().y, length, 0.0f, prevSeg.get() )); } } auto& endSeg = segments.back(); endSeg->drag(0, 0); }
方案3:先创建所有Segment,再统一设置父指针
先将所有Segment加入vector,待vector稳定后,再遍历设置每个节点的父指针,此时内存地址不会再变化。
需要先给Segment类添加一个setParent方法:
class Segment { // ... 原有代码 ... public: void setParent(Segment* ip) { parent = ip; hasParent = (ip != nullptr); } // ... 原有代码 ... };
修改后的main函数:
int main() { std::vector<Segment> segments; size_t segment_amt = 10; int length = 0; // 先创建所有Segment,暂不设置父指针 for (int i = 0; i < segment_amt; i++) { segments.push_back(Segment(0.0f, 0.0f, length, 0.0f)); } // 遍历设置父指针 for (int i = 1; i < segment_amt; i++) { segments[i].setParent(&segments[i-1]); } Segment& endSeg = segments.back(); endSeg.drag(0, 0); }
额外注意点
0xFFFFFFFFFFFFFFF7是野指针的典型标记值,说明你访问了已被释放的内存空间。- 使用
std::vector时必须牢记:当元素数量超过当前容量时,所有迭代器、指针、引用都会失效。
内容的提问来源于stack exchange,提问作者SoulDaMeep
相关产品推荐
相关产品推荐

