DLL中的堆错误

时间:2012-04-20 10:59:57

标签: c dll malloc

我正在寻找一些C dll编程方面的帮助。我在Visual Studio中遇到错误,当我在dll中调用free时发生错误。程序在IDE中的调试模式下运行正常,但是当我尝试将其作为“Start without debugging”执行时,程序崩溃了。我通过调试读到了堆,这是堆共享的,这可能解释了为什么代码在F5而不是Ctrl-F5下正常运行。这是正确的吗?

我已经四处搜索了,并且我了解到通过dll-exe边界传递动态分配的内存是危险的,但是当我调用malloc并且在同一个dll中释放时,这应该不是问题。我已经发布了以下代码。任何帮助将不胜感激。请注意,此代码适用于我的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;
}

1 个答案:

答案 0 :(得分: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?