我最近在c ++对象创建中遇到了问题。这个问题有点像问题 C++ strange segmentation fault by object creation ,但这里的代码是开源项目的一部分,可能没有简单的错误。
在方法中调用对象创建,并且通过两个连续步骤调用该方法。
该类在strtokenizer.h中定义如下:
class strtokenizer {
protected:
vector<string> tokens;
int idx;
public:
strtokenizer(string str, string seperators = " ");
void parse(string str, string seperators);
int count_tokens();
string next_token();
void start_scan();
string token(int i);
};
在strtokenizer.cpp中,就像这样:
using namespace std;
strtokenizer::strtokenizer(string str, string seperators) {
parse(str, seperators);
}
void strtokenizer::parse(string str, string seperators) {
int n = str.length();
int start, stop;
if (flag) {
printf("%d\n", n);
}
start = str.find_first_not_of(seperators);
while (start >= 0 && start < n) {
stop = str.find_first_of(seperators, start);
if (stop < 0 || stop > n) {
stop = n;
}
tokens.push_back(str.substr(start, stop - start));
start = str.find_first_not_of(seperators, stop + 1);
}
start_scan();
}
int strtokenizer::count_tokens() {
return tokens.size();
}
void strtokenizer::start_scan() {
idx = 0;
return;
}
string strtokenizer::next_token() {
if (idx >= 0 && idx < tokens.size()) {
return tokens[idx++];
} else {
return "";
}
}
string strtokenizer::token(int i) {
if (i >= 0 && i < tokens.size()) {
return tokens[i];
} else {
return "";
}
}
创建strtokenizer对象的方法如下:
int dataset::read_wordmap(string wordmapfile, mapword2id * pword2id) {
pword2id->clear();
FILE * fin = fopen(wordmapfile.c_str(), "r");
if (!fin) {
printf("Cannot open file %s to read!\n", wordmapfile.c_str());
return 1;
}
char buff[BUFF_SIZE_SHORT];
string line;
fgets(buff, BUFF_SIZE_SHORT - 1, fin);
int nwords = atoi(buff);
for (int i = 0; i < nwords; i++) {
fgets(buff, BUFF_SIZE_SHORT - 1, fin);
line = buff;
strtokenizer strtok(line, " \t\r\n");
if (strtok->count_tokens() != 2) {
continue;
}
pword2id->insert(pair<string, int>(strtok->token(0), atoi(strtok->token(1).c_str())));
}
fclose(fin);
return 0;
}
首次运行read_wordmap()方法时(第一次调用read_wordmap()),&#39; strtok&#39;对象创建大约87k次,在第二次(第二次read_wordmap()调用),该对象预计运行超过88k次。但是,在第二个方法调用中,它会在以下行中引发错误(有时&#39;分段错误&#39;有时&#39;内存损坏(快速)&#39;)约86k次:
strtokenizer strtok(line, " \t\r\n");
当对象创建的代码块被修改为如下所示时,将没有错误。
strtokenizer *strtok = new strtokenizer(line, " \t\r\n");
printf("line: %s", line.c_str());
if (strtok->count_tokens() != 2) {
continue;
}
pword2id->insert(pair<string, int>(strtok->token(0), atoi(strtok->token(1).c_str())));
答案 0 :(得分:0)
您的代码中看起来有内存损坏。您应该考虑使用像valgrind(http://valgrind.org/)这样的工具来检查代码是否写出超出范围。
您修改后的代码使用堆内存而不是堆栈内存,这可能会隐藏问题(即使它仍然存在)。
通过阅读您的代码,在提供的wordmapfile
有一些意外数据的情况下,有几个缺失的测试可确保安全处理。
例如,你不检查fgets的结果,所以如果文件开头的单词数大于实际单词数,你就会遇到问题。
答案 1 :(得分:0)
我在@Paul R和其他朋友的建议下仔细调试了我的代码,发现这是因为我没有堆栈中的空闲内存。 上面提出的代码是我项目的一小部分,在项目中,gibbs采样算法应该运行一千次(迭代)。
在每次迭代中,旧矩阵应该被释放,新的矩阵将被“新出”。但是,我忘了释放所有矩阵和列表,这就是我的程序破坏的原因。
我上面发布代码的原因是每次遇到代码时程序都会崩溃:
strtokenizer strtok(line, " \t\r\n");
对象“strtok”将在文件中运行1000 *行(10000+行)。所以它让我觉得可能创建了太多的对象并占用了所有的堆栈内存。即使我发现没有必要手动释放它们。
在visual studio中调试程序时,内存占用率监视器在每次迭代中都显示出急剧增长,并且偶尔发生“bad_alloc”错误。这些让我意识到我忘了释放一些大的动态矩阵。
谢谢大家! 我为错误描述的占用你时间的问题道歉!