TL; DR:永远记住std :: vector需要在数据增长时移动你的数据,这会使你仍然浮动的任何指针无效。
我已经搜索了一下这个问题,似乎我遇到的每个案例都是在同一个指针上调用delete两次的问题。我正在编写一个小程序而且我正在获得堆损坏,但堆分配的唯一事情就是c ++标准库。我有预感我正在泄漏对局部变量的引用或者做了多态的错误,但我无法弄明白。
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
struct Project;
struct Solution;
struct Line {
string command;
vector<string> params;
void print(ostream &os) {
os << command << ": ";
for (string s : params)
os << s << ' ';
os << endl;
}
};
struct Properties {
vector<string> includes;
vector<string> libPaths;
vector<string> libs;
vector<string> sources;
vector<string> headers;
vector<Project *> depends;
string folder;
string name;
string type;
};
struct Project : Properties {
Project() { built = false; }
bool built;
void build() {
if (built)
return;
built = true;
for (Project *p : depends)
p->build();
cout << "Building project: " << name << endl;
}
};
struct Solution : Properties {
public:
Project *getProject(const string &name) {
for (Project &p : projects) {
if (p.name == name)
return &p;
}
// No project with such a name -- create it
Project p;
cout << &p << endl;
p.name = name;
projects.push_back(p);
cout << "Created project: " << name << endl;
return getProject(name);
}
private:
vector<Project> projects;
};
Line parseLine(const string &strline) {
istringstream stream(strline);
Line line;
stream >> line.command;
while (stream.good()) {
string tok;
stream >> tok;
if (tok.length() > 0)
line.params.push_back(tok);
}
return line;
}
template <typename T>
vector<T> concat(const vector<T> &a, const vector<T> &b) {
vector<T> vec;
for (T obj : a)
vec.push_back(obj);
for (T obj : b)
vec.push_back(obj);
return vec;
}
template <typename T>
void printVector(ostream os, vector<T> v) {
for (T obj : v)
os << obj;
os << endl;
}
int main(int argc, char *argv[]) {
Solution solution;
Properties *properties = &solution;
ifstream stream("testproj.txt");
Project p[100]; // No error here....
string linestr;
for (int lineNum = 1; getline(stream, linestr); lineNum++) {
Line line = parseLine(linestr);
if (line.command == "solution") {
// Make future commands affect the solution
properties = &solution;
} else if (line.command == "exe" || line.command == "lib") {
if (line.params.size() != 1) {
cerr << "Error at line " << lineNum << endl;
return 1;
}
// Make future commands affect this project
properties = solution.getProject(line.params[0]);
properties->type = line.command;
properties->name = line.params[0];
} else if (line.command == "includes") {
properties->includes = concat(properties->includes, line.params);
} else if (line.command == "libpath") {
properties->libPaths = concat(properties->libPaths, line.params);
} else if (line.command == "libs") {
properties->libs = concat(properties->libs, line.params);
} else if (line.command == "folder") {
if (line.params.size() != 1) {
cerr << "Error at line " << lineNum << endl;
return 1;
}
properties->folder = line.params[0];
} else if (line.command == "source") {
properties->sources = concat(properties->sources, line.params);
} else if (line.command == "header") {
properties->headers = concat(properties->headers, line.params);
} else if (line.command == "depends") {
Project *proj;
for (string projName : line.params) {
proj = solution.getProject(projName);
properties->depends.push_back(proj);
}
}
}
}
错误:
HEAP: Free Heap block 00395B68 modified at 00395BAC after it was freed
这是我的堆栈跟踪(抱歉上面的源代码中没有行号):
crashes in malloc & ntdll somewhere up here
libstdc++ ---- incomprehensible name mangling
main.cpp, line 24 (inside Properties::Properties()): (compiler-generated constructor)
main.cpp, line 37 (inside Project::Project()): Project() { built = false; }
main.cpp, line 62 (inside Solution::getProject()): Project p;
main.cpp, line 150 (inside main()): proj = solution.getProject(projName);
它似乎在属性的默认构造函数中崩溃了?也许在构建矢量时?
编辑: 输入文件,如果有帮助:
solution
includes deps/include deps/include/SDL2
libpath deps/lib
libs opengl32 glu32 SDL2main SDL2 libpng16 glew
exe game
folder game
source main.cpp
depends render common
lib render
folder render
source Shader.cpp
header TODO
depends common
lib common
folder common
source util.cpp
header TODO
答案 0 :(得分:4)
这是很多代码,但有一个很大的可能性是你要取消引用getProject
返回的指针之一,但这已经失效,因为向量projects
,它持有指向的对象,已经执行了重新分配。这会使所有指针,引用和迭代器无效。
执行此操作时:
projects.push_back(p);
projects
可能需要增长,这会导致重新分配和上面提到的指针无效。
如果不深入研究代码,看起来您可以使用Solution
轻松实现std::map
:
struct Solution : Properties
{
public:
// Check for project with name "name"
// Add one if it doesn't exist
// return it
Project& getProject(const std::string& name)
{
if (!projects.count(name))
{
projects[name].name = name;
}
return projects[name];
}
// Return project with name "name" or raise exception
// if it doesn't exist
const Project& getProject(const string &name) const
{
return projects.at(name);
}
private:
std::map<std::string, Project> projects;
};