我有以下结构:
typedef struct block {
char *hash;
char *data;
char *previousHash;
} Block;
typedef struct blockchain {
Block** chain;
size_t length;
} Blockchain;
连同以下功能:
char* generate_hash(char* toHash) {
return "[ placeholder ]";
}
Block* make_block(char* data, char* previousHash) {
size_t hash_size = 65 * sizeof(char);
size_t data_size = ( 1 + strlen(data)) * sizeof(data);
Block* new_block = malloc(2 * hash_size + data_size);
new_block->data = data;
new_block->previousHash = previousHash;
char toHash[strlen(data) + strlen(previousHash) + 1];
strcpy(toHash, data);
strcat(toHash, previousHash);
new_block->hash = generate_hash(toHash);
return new_block;
}
Block* make_genesis() {
return make_block("Genesis Block", "");
}
Blockchain* make_blockchain() {
Block *blockchain[] = { make_genesis() };
Blockchain* bc = malloc(8 + sizeof(size_t));
bc->chain = blockchain;
bc->length = 1;
return bc;
}
void display_blockchain(Blockchain *bc_ptr) {
for (int i = 0; i < bc_ptr->length; i++) {
printf("Block Number %d\n", i);
printf("\tHash: %s\n", bc_ptr->chain[i]->hash);
}
}
然后我像这样调用这些函数:
int main(int argc, char *argv[]) {
Blockchain* my_blockchain = make_blockchain();
display_blockchain(my_blockchain);
Block* new_block = make_block("sdf", "sdf");
display_blockchain(my_blockchain);
return 0;
}
第一次调用 display_blockchain 时,它按预期工作。但是,第二次调用它时,程序由于分段错误而崩溃。 make_block 无法访问 my_blockchain,所以我不确定为什么两者会导致不同的结果。
答案 0 :(得分:0)
您正在使用在其范围之外的堆栈上分配的一些内存地址:
Block *blockchain[] = { make_genesis() }; // This is Block** allocated on stack
Blockchain* bc = malloc(8 + sizeof(size_t));
bc->chain = blockchain; // Here you assign the stack address of Block**
bc->length = 1;
return bc;
然后当您稍后访问它时,它会生成分段错误。
为什么第一次不崩溃?嗯,这纯属巧合。这主要是因为当函数返回时,剩余的内存并没有被清除。调用display函数时,函数并没有大到覆盖栈上剩余的内存,指针中的栈地址其实是完整的。但是,如果您调用更复杂的函数,例如 make_block
,它将覆盖堆栈上的内容,从而破坏您“期望”找到 bc->chain
变量的堆栈地址。>
解决方案是这一行 Block *blockchain[] = { make_genesis() };
需要被 malloc 代替。