2012-04-20 55 views
1

我正在寻找一些C DLL的编程帮助。我在Visual Studio中遇到了一个错误,当我从dll中调用free时发生错误。该程序在IDE中的调试模式下运行良好,但是当我试图将其作为“无调试开始”执行时,程序崩溃。我在调试过程中看到这个堆是共享的,这可能解释了为什么代码可以使用F5而不是Ctrl-F5运行。它是否正确??DLL中的堆错误

我搜遍了,我知道通过dll-exe边界传递动态分配的内存是危险的,但是因为我在同一个dll中调用malloc和free,所以这应该不成问题。我已经发布了下面的代码。任何帮助将不胜感激。请注意,这段代码适用于我的Linux机器,我只是试图将它移植到Windows上,以获得Windows中的体验编程。 谢谢

#ifndef HASHTABLE_H 
#define HASHTABLE_H 

// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the HASHTABLE_EXPORTS 
// symbol defined on the command line. This symbol should not be defined on any project 
// that uses this DLL. This way any other project whose source files include this file see 
// HASHTABLE_API functions as being imported from a DLL, whereas this DLL sees symbols 
// defined with this macro as being exported. 
#ifdef HASHTABLE_EXPORTS 
#define HASHTABLE_API __declspec(dllexport) 
#else 
#define HASHTABLE_API __declspec(dllimport) 
#endif 

#ifdef __cplusplus 
extern "C" { 
#endif 

/** 
    * This is a naive implementation 
    * of a hashtable 
    */ 

typedef struct node { 
    struct node *next; 
    char *value; 
    char *key; 
} Node; 

typedef struct hashtable { 
    struct node **nodes; 
    int num_elements; 
    int size; 
    int (*hash_function)(const char * const); 
} Hashtable_str; 

// Construction and destruction 
HASHTABLE_API void tbl_construct(Hashtable_str **table); 
HASHTABLE_API void tbl_destruct(Hashtable_str *table); 

// Operations 
HASHTABLE_API int tbl_insert (Hashtable_str *table, const char * const key, const char * const element); // return the key 
HASHTABLE_API int tbl_remove(Hashtable_str *table, const char * const key); 
HASHTABLE_API char * tbl_find(Hashtable_str *table, const char * const key); // return the element 
HASHTABLE_API int size(Hashtable_str *table); // Return the size 

// default hash function 
int def_hash(const char * const key); 

#ifdef __cplusplus 
} 
#endif 

#endif 

下面是实现代码

// hashtable.cpp : Defines the exported functions for the DLL application. 
// 

#include "stdafx.h" 
#include "hashtable.h" 
#include <stdlib.h> // for memcpy 
#include <stdio.h> 
#include <string.h> 

#define SIZE 100 

int def_hash(const char * const key) 
{ 
    // simply sum the ascii 
    // values and take modulo 
    // 100 
    //int i; 
    //int sum; 
    //sum = 0; 
    //for (i=0; key[i] != '\0'; i++) 
    // sum += key[i]; 
    //return sum % SIZE; 

    return 0; 
} 

// construct a hashtable and return a pointer 
HASHTABLE_API void tbl_construct(Hashtable_str **tbl) 
{ 
    int i; 
    Hashtable_str *tbl_ptr; 
    *tbl = (Hashtable_str*) malloc (sizeof(Hashtable_str*)); 
    tbl_ptr = *tbl; 

    tbl_ptr->nodes = (Node**) malloc (SIZE * sizeof(Node*)); 
    for (i=0; i < SIZE; i++) tbl_ptr->nodes[i] = NULL; 
    tbl_ptr->hash_function = &def_hash; 
    tbl_ptr->num_elements = 0; 
    tbl_ptr->size = SIZE; 
} 

HASHTABLE_API void tbl_destruct(Hashtable_str *tbl) 
{ 
    void free_tbl_node(Node*); // declare the release function 

    int i; 
    for (i=0; i < tbl->size; i++) 
    { 
     if (tbl->nodes[i] != NULL) 
      free_tbl_node(tbl->nodes[i]); 
    } 
} 

void free_tbl_node(Node *curr_node) 
{ 
    if (curr_node->next != NULL) 
     free_tbl_node(curr_node->next); 

    free(curr_node->value); 
    curr_node->value = NULL; 
    free(curr_node->key); 
    curr_node->key = NULL; 
    //free(curr_node); 

    //Node *temp = NULL; 
    //Node *temp2 = NULL; 

    //temp = temp2 = curr_node; 
    //while (temp->next != NULL) 
    //{ 
    // temp2=temp->next; 
    // free(temp->key); 
    // free(temp->value); 
    // free(temp); 
    // temp=temp2; 
    //} 
} 

// table operations 
HASHTABLE_API int count(Hashtable_str *tbl) { return tbl->num_elements; } 
HASHTABLE_API int size(Hashtable_str *tbl) { return tbl->size; } 

HASHTABLE_API int tbl_insert(Hashtable_str *table, const char * const key, const char * const element) 
{ 
    int hash; 
    Node *temp_ptr = NULL; 
    hash = table->hash_function(key); 

    // printf("Placing into column %d\n", hash); 

    if (table->nodes[hash] == NULL) 
    { 
     table->nodes[hash] = (Node*) malloc(sizeof(Node*)); 
     temp_ptr = table->nodes[hash]; 
     temp_ptr->next = NULL; 
     temp_ptr->key = (char*) malloc (strlen(key) + 1 * sizeof(char)); 
     temp_ptr->value = (char*) malloc (strlen(element) + 1 * sizeof(char)); 
     strcpy_s(temp_ptr->key, strlen(key)+1, key); 
     strcpy_s(temp_ptr->value, strlen(element)+1, element); 
     table->num_elements += 1; 
    } 
    else 
    { 
     // Collision!! 
     temp_ptr = table->nodes[hash]; 
     while (temp_ptr->next != NULL) 
      temp_ptr = temp_ptr->next; 

     temp_ptr->next = (Node*) malloc(sizeof(Node)); 
     temp_ptr->next->key = (char*) malloc (strlen(key)+1 * sizeof(char)); 
     temp_ptr->next->value = (char*) malloc (strlen(element)+1 * sizeof(char)); 
     temp_ptr->next->next = NULL; 
     strcpy_s(temp_ptr->next->key, strlen(key)+1, key); 
     strcpy_s(temp_ptr->next->value, strlen(element)+1, element); 
     table->num_elements += 1; 
    } 

    // Return the hash value itself for hacking 
    return hash; 
} 

HASHTABLE_API int tbl_remove(Hashtable_str *tbl, const char * const key) 
{ 
    int hash; 
    Node *temp_ptr = NULL; 
    Node *chain = NULL; 
    hash = tbl->hash_function(key); 

    if (tbl->nodes[hash] == NULL) 
     return 1; 
    else 
    { 
     temp_ptr = tbl->nodes[hash]; 

     if (strcmp(key, temp_ptr->key) == 0) 
     { 
      // The next node is the node in question 
      chain = temp_ptr->next; 
      free(temp_ptr->value); 
      printf("Deleted the value\n"); 
      free(temp_ptr->key); 
      printf("Deleted the key\n"); 
      //printf("About to delete the node itself\n"); 
      //free(temp_ptr); 
      tbl->nodes[hash] = chain; 
      tbl->num_elements -= 1; 
      return 0; 
     } 
     else 
     { 
      while (temp_ptr->next != NULL) 
      { 
       if (strcmp(key, temp_ptr->next->key) == 0) 
       { 
        // The next node is the node in question 
        // So grab a pointer to the node after it 
        // and remove the next node 
        chain = temp_ptr->next->next; 
        free(temp_ptr->next->key); 
        free(temp_ptr->next->value); 
        //free(temp_ptr->next); 
        temp_ptr->next = chain; 
        tbl->num_elements -= 1; 
        return 0; 
       } 
       else 
        temp_ptr = temp_ptr->next; 
      } 
     } 

     // Couldn't find the node, so declare not existent 
     return 1; 
    } 
} 

HASHTABLE_API char * tbl_find(Hashtable_str *tbl, const char * const key) 
{ 
    // Compute the hash for the index 
    int hash; 
    Node *temp_ptr = NULL; 
    hash = tbl->hash_function(key); 

    if (tbl->nodes[hash] == NULL) 
     return NULL; 
    else 
    { 
     temp_ptr = tbl->nodes[hash]; 

     if (strcmp(key, temp_ptr->key) != 0) 
     { 
      while (temp_ptr->next != NULL) 
      { 
       temp_ptr = temp_ptr->next; 
       if (strcmp(key, temp_ptr->key) == 0) 
        return temp_ptr->value; 
      } 
     } 

     // Couldn't find the node, so declare not existent 
     return NULL; 
    } 
} 

这里是我的主

#include <hashtable.h> 
#include <utils.h> 
#include <stdio.h> 

int main(int argc, char **argv) 
{ 
    int i=0; 
    Hashtable_str *my_table = NULL; 
    tbl_construct(&my_table); 

    tbl_insert(my_table, "Daniel", "Student"); 
    tbl_insert(my_table, "Derek", "Lecturer"); 
    //tbl_insert(my_table, "Melvyn", "Lecturer"); 

    tbl_print(my_table); 

    printf("\nRemoving Daniel...\n"); 
    tbl_remove(my_table, "Daniel"); 
    //tbl_print(my_table); 

    tbl_destruct(my_table); 
    my_table = NULL; 

    scanf_s("%d", &i); 
    return 0; 
} 
+0

您有多个电话在你的代码来释放。如果您指出哪一个导致错误,这将有所帮助。并告诉我们错误是什么。 – 2012-04-20 11:04:23

+0

@Lancophon你也不需要粘贴你的整个程序,只需要粘贴与你的问题相关的部分。 – sashoalm 2012-04-20 11:05:34

+0

@PaulMitchell道歉不清楚。错误的调用是在tbl_remove()函数中,在“已删除的键”printf语句之前 – Lancophone 2012-04-20 11:10:53

回答

1

这是不正确的分配指针的大小,而不是一个Hashtable_str

*tbl = (Hashtable_str*) malloc (sizeof(Hashtable_str*)); 

它应该是:

*tbl = malloc(sizeof(Hashtable_str)); 

同一个问题有:

table->nodes[hash] = (Node*) malloc(sizeof(Node*)); 

Do I cast the result of malloc?

+0

非常感谢您的回复。我已经做出了修改(对于我而言,我很抱歉)。但是,这并没有弥补崩溃 – Lancophone 2012-04-20 11:16:41

+0

@Lancophon,更新的答案。 – hmjd 2012-04-20 11:18:10

+0

该更新修正了它!非常感谢!!但是,这又提出了另一个问题。为什么这个代码在Linux下使用gcc进行编译和执行? – Lancophone 2012-04-20 11:21:17