我正在实施一个跳过列表。它是什么并不重要,但它现在适用于 1000 个节点,但不适用于 10000 个节点。我得到了没有意义的 SegFaults,所以我打印了一些变量。令我惊讶的是,很多不应该改变的东西,变成了垃圾值。例如,我在函数 insertNode 之前和之后打印 inputValue。它有时会重置为零,而应始终递增。我们看代码(跳过读取文件输入,问题发生在while循环):
int main(int argc, char** argv) {
string filename = "";
if( argc == 2 )
filename = argv[1];
else
return 0;
list = new skiplist();
fstream inputFile(filename.c_str(), ios_base::in);
inputFile >> numberofnodes;
inputFile >> list->minimumKey;
inputFile >> list->maximumKey;
printf("%d\n", numberofnodes);
printf("%d\n", list->minimumKey);
printf("%d\n", list->maximumKey);
list->Maxlevel = 1;
list->header = new node();
list->tail = new node();
list->header->key = list->minimumKey;
list->tail->key = list->maximumKey;
for ( int i=1; i<=MAXIMUMLEVEL; i++ ) {
list->header->forward[i] = list->tail;
list->tail->forward[i] = NULL;
}
int sanityCheck = 134153;
// insert nodes
int inputKey;
int inputValue = 0;
int * keys = new int[numberofnodes];
while (inputFile >> inputKey)
{
inputValue++;
keys[inputValue] = inputKey;
insertNode(inputKey, inputValue);
if(sanityCheck != 134153) // dark magic changes this value
keys[9999999999999999999999]++; // program crashes here
// it would otherwise crash on while
}
printf("\n\nNodes inserted: %d\n\n",inputValue);
我跑了 Valgrind。无效的内存写入/读取发生在变量发生变化之后,至少我相信如此。这就是我添加完整性检查的原因。正如我所想的那样,在尝试访问密钥之前没有无效的内存写入/读取[9999999999999999999999]。但是该行只能运行 int sanitycheck 已更改,而我从来没有这样做过。
最后,这是 insertNode 的代码。我看不到任何可能导致这种情况的东西:
void insertNode(int newKey, int newValue){
node * update[MAXIMUMLEVEL];
node * auxNode = list->header;
for(int i=list->Maxlevel; i >=1; i--) {
while ( auxNode->forward[i]->key < newKey ) {
auxNode = auxNode->forward[i];
}
update[i] = auxNode;
}
auxNode = auxNode->forward[1];
if ( auxNode->key == newKey ) {
auxNode->value = newValue;
} else {
int randomLevel = 1;
while ( (rand() / double(RAND_MAX)) < LEVELPROBABILITY && randomLevel < MAXIMUMLEVEL ) {
randomLevel++;
}
if ( randomLevel > list->Maxlevel ) {
for ( int i = list->Maxlevel+1; i <= randomLevel; i++ ) {
update[i] = list->header;
}
list->Maxlevel = randomLevel;
}
node * newNode = new node();
newNode->key = newKey;
newNode->value = newValue;
for ( int i=1; i<=MAXIMUMLEVEL; i++ ) {
newNode->forward[i] = NULL;
}
for ( int i=1; i<=list->Maxlevel; i++ ) {
newNode->forward[i] = update[i]->forward[i];
update[i]->forward[i] = newNode;
}
}
}
和结构:
typedef struct node {
int key;
int value;
node * forward[MAXIMUMLEVEL+1];
}node;
struct skiplist {
int minimumKey;
int maximumKey;
int Maxlevel;
node * header;
node * tail;
};
EDIT:
#define MAXIMUMLEVEL 16
#define LEVELPROBABILITY 0.5
我什至没有使用 malloc。有指针操作,但是 valgrind 应该检测我是否做错了什么,对吗?如果我的内存不足,就会出现异常。我创建但从不访问/写入/更改的 int 怎么可能被修改?对不起,很长的帖子,但我不知道问题可能出在哪里。
没有完整性检查的 Valgrind 输出(键 [999...9]): http: //pastebin.com/hWH3fri2
第 155 行是 while (inputFile >> inputKey)