TL;DR: always remember that std::vector needs to move your data around when it grows, which invalidates any pointers you still have floating around.
I've googled around for this problem a bit, and it seems every case I came across was a question of calling delete on the same pointer twice. I'm writing a small program and I'm getting heap corruption, but the only thing doing heap allocation is the c++ standard library. I have a hunch I'm leaking a reference to a local variable or done something wrong with polymorphism, but I can't figure it out.
#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);
}
}
}
}
The error:
HEAP: Free Heap block 00395B68 modified at 00395BAC after it was freed
Here is my stack trace (sorry no line numbers in the source above):
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);
It seems to be crashing in the default constructor for Properties? Perhaps while constructing a vector?
Edit: The input file, if it would help:
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