两个相同函数调用的不同结果

时间:2021-07-01 17:53:30

标签: c

我有以下结构:

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,所以我不确定为什么两者会导致不同的结果。

1 个答案:

答案 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 代替。

相关问题