Reputation: 328
I have the following structures:
typedef struct block {
char *hash;
char *data;
char *previousHash;
} Block;
typedef struct blockchain {
Block** chain;
size_t length;
} Blockchain;
Along with the following functions:
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);
}
}
I then call those functions like so:
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;
}
The first time display_blockchain is called, it works as intended. However, the second time it is called, the program crashes due to a segmentation fault. make_block has no access to my_blockchain, so I am not sure why the two would result in different outcomes.
Upvotes: 0
Views: 72
Reputation: 1479
You are using some memory address allocated on stack outside its scope:
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;
Then when you access it later, it generates a segmentation fault.
Why doesn't it crash the first time? Well, this is pure coincidence. This is mainly because when the function returns, the memory leftovers are not wiped out. When you call the display function, the function is not so big to overwrite the memory leftovers on the stack, and the stack address in the pointer is actually intact. But if you call a more complex function, like make_block
, it will get to overwrite the contents on the stack, thus corrupting the stack address where you would "expect" to find your bc->chain
variable.
The solution is that this line Block *blockchain[] = { make_genesis() };
needs to be malloc'd instead.
Upvotes: 1