释放内存分配

时间:2018-02-14 03:15:52

标签: c++ malloc free

我无法弄清楚这个错误究竟意味着什么。它说:

map-test(29262,0x7fffb118e340) malloc: *** error for object 0x7fa5d7001000: pointer being freed was not allocated

但是,我很确定它是分配的。以下是有问题的功能。我想我可能会把记忆搞砸到某个地方,但我不会认为是这样的,但是我再次对这些事情感到陌生,我的教授喜欢指点虔诚地(可悲地)。有人能引导我朝着正确的方向前进吗?提前谢谢了。

map.cpp

#include "map.hpp"
#include <string>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>

Map::Map() {
    database = new MapEntry*[DATABASE_SIZE];
    for (int i = 0; i < DATABASE_SIZE; i++){
        database[i] = new MapEntry("", 0);
    }
}

/* Adds (inserts) val with the associated key.
 * Returns if successful or not.  (It is not successful if we are out of
 * memory, or if the key already exists.)
 */
bool Map::add(const char *key, int val) {
    for (int i = 0; i < DATABASE_SIZE; i++)
        if (database[i]->getVal() == 0) {
            database[i]->setVal(val);
            database[i]->setKey(key);
            return true;
        }
    return false;
}

/* Searches for the key.  If found it sets ret to the correct val and
 * returns true.  Otherwise this function returns false.
 */
bool Map::get(const char *key, int &ret) {
    for (int i = 0; i < DATABASE_SIZE; i++){
        if (database[i]->getKey() == key) {
            ret = database[i]->getVal();
            return true;
        }
    }
    return false;
}

/* Returns the size (memory consumed) by this data structure. */
int Map::size() {
    int totalsize = 0;
    for (int i = 0; i < DATABASE_SIZE; i++){
        if (database[i]->getVal() != 0) {
            totalsize += sizeof(database[i]);
        }
    }
    return totalsize;
}

/* Removes the current value from the Map AND frees up any memory that it can.
 * Returns true if there was something to remove, false otherwise.
 */
bool Map::remove(const char *key) {
    for (int i = 0; i < DATABASE_SIZE; i++){
        if (database[i]->getKey() == key) {
            database[i]->setKey("");
            database[i]->setVal(0);
            return true;
        }
    }
    return false;
}

/* Returns the number of names with a given prefix.
 * EX: If we have {John, Jonathan, Paul, Mark, Luke, Joanna} then
 * howMany("Jo") == 3
 */
int Map::howMany(const char *prefix) {
    int count = 0;
    std::string beginning(prefix);
    for (int i = 0; i < DATABASE_SIZE; i++){
        std::string key(database[i]->getKey());
        if (key.substr(0, beginning.size()).compare(beginning) == 0) {
            count++;
        }
    }
    return count;
}

/* Frees all memory */
Map::~Map() {
for (int i = 0; i < DATABASE_SIZE; i++) {
        delete database[i];
    }
    delete[] database;
}

map.hpp

#ifndef MAP_H
#define MAP_H

const int DATABASE_SIZE = 1024;

class MapEntry{
    private:
        int mIDVal;
        const char* mKeyName;

    public:
        MapEntry(const char *key, int val) {
        mKeyName = key;
        mIDVal = val;
    }
    int getVal(){
        return mIDVal;
    }
    const char* getKey(){
        return mKeyName;
    }
    void setVal(int val){
        mIDVal = val;
    }
    void const setKey(const char* key){
        mKeyName = key;
    }
};

class Map{
    public:
        Map();

        bool add(const char *key, int val);

        void print();

        bool get(const char *key, int &ret);

        int size();

        bool remove(const char *key);

        int howMany(const char *prefix);

    ~Map();
private:
    MapEntry **database;
    Map(const Map &m){
        // Copy constructor in private to avoid double deleting.
    }
};

#endif

的main.cpp

#include <stdlib.h>
#include <iostream>
#include "map.hpp"

using namespace std;

int main(int argc, char *argv[]) {
    Map myMap;
    myMap.add("Philip Fry", 51798);
    myMap.add("Turanga Leela", 987651234);
    myMap.add("Philip Fry", 89715);
    int pringles = 0;
    myMap.get("Philip Fry", pringles);
    cout << pringles << "\n";
    myMap.print();
    cout << myMap.size() << "\n";
    cout << "\n";
    myMap.remove("Philip Fry");
    myMap.print();
    pringles = 0;
    myMap.get("Philip Fry", pringles);
    cout << pringles << "\n";
    const char* prefix = "Phi";
    cout << myMap.howMany(prefix) << "\n";

    myMap.~Map();
    return 0;
}

1 个答案:

答案 0 :(得分:0)

当你直接调用析构函数时,你可以在这里双重释放内存。你不应该手动调用析构函数。当对象超出范围时,它会自动调用。有双重删除。

myMap.~Map();  ///< this is wrong (get rid of it)

如果您想要视觉证据表明析构函数被调用了两次,那么请将其修改为打印。

/* Frees all memory */
Map::~Map() {
    std::cout << "Map::~Map() invoked!" << std::endl;
    for (int i = 0; i < DATABASE_SIZE; i++) {
        delete database[i];
    }
    delete[] database;
}