std :: vector :: resize导致模板类崩溃

时间:2014-06-21 05:18:15

标签: c++ stl

这里是代码: 崩溃的地方标有评论(//////crash)。 我不知道导致问题的原因。 enter image description here

在我打印从文件中获取的数据大小后,它会显示' 1'表示该数组应该只包含1个元素。因此,似乎没有' bad_allocate错误' ... 你们能帮助我吗?非常感谢你的帮助。 :)

#include<stdio.h>
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#include<string.h>
#include<type_traits>
using namespace std;

bool read_int(int& val,FILE*& fp)
{
    if(fp == nullptr)
        return false;
    fread(&val,sizeof(int),1,fp);
    return true;
}

bool write_int(int val,FILE*& fp)
{
    if(fp == nullptr)
    {
        return false;
    }
    fwrite(&val,sizeof(int),1,fp);
    return true;
}


struct SANOBJ
{
    char path[128];
    char nickname[40];
    SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
    {
        if(_p == nullptr || _n == nullptr)
            *this = {};
        int m = strlen(_p),n = strlen(_n);
        if(m < 128) strcpy(path,_p);
        if(n < 40) strcpy(nickname,_n);
    }
    ~SANOBJ(){}
    SANOBJ(const SANOBJ& other)
    {
        memcpy(path,other.path,sizeof(char) * 128);
        memcpy(nickname,other.nickname,sizeof(char) * 40);
    }
    bool operator < (const SANOBJ& other) const
    {
        return string(path) < string(other.path);
    }
    bool operator == (const SANOBJ& other) const
    {
        return (strcmp(other.path,path) == 0);
    }
};

template <typename source_type>     //the 'source_type' type need to have the member 'int m_index'
class FrameQueue
{
public:
    FrameQueue()    //fill the 1st frame automatically
    {
        source_type new_node;
        new_node.m_index = 0;
        m_data.push_back(new_node);
    }
    FrameQueue(const FrameQueue& other)
    {
        m_data = other.m_data;
    }

    bool AddFrame(const source_type& other) // keeps an ascending order
    {
        int index = _binary_search(other);
        if(index != -1)
        {
            return false;
        }
        m_data.insert(std::upper_bound(m_data.begin(),m_data.end(),other,
                                    [](const source_type& a,const source_type& b)->bool const{return a.m_index < b.m_index;}
                                    ),other);
        return true;
    }

    bool DeleteFrameByElemIndex(int elemIndex)  //delete frame according to the index of frame in the queue
    {
        if(elemIndex < 0)
            return false;
        if(elemIndex >= m_data.size())
            return false;
        typename std::vector<source_type>::iterator it ;
        it = m_data.begin() + elemIndex;
        it = m_data.erase(it);
        return true;
    }

    bool DeleteFrameByFrameIndex(int frameIndex)
    {
        source_type node = {};
        node.m_index = frameIndex;
        int index = _binary_search(node);
        if(index == -1)
        {
            return false;
        }
        typename std::vector<source_type>::iterator it;
        it = m_data.begin() + index;
        it = m_data.erase(it);
        return true;
    }

    bool Clear()        // There would always be a single frame
    {
        source_type new_node = {};
        new_node.m_index = 0;
        m_data.clear();
        m_data.push_back(new_node);
        return true;
    }

    bool WriteFile(FILE*& fp)
    {
        if(fp == nullptr)
            return false;
        bool result = write_int(m_data.size(),fp);
        if(result == false)
            return false;
        fwrite(&(m_data[0]),sizeof(source_type),m_data.size(),fp);
        return true;
    }

    bool ReadFile(FILE*& fp)
    {
        if(fp == nullptr)
            return false;
        int data_size;
        bool result = read_int(data_size,fp);
        if(result == false)
            return false;
        if(data_size > 0)
        {
            m_data.resize(data_size);
            fread(&(m_data[0]),sizeof(source_type),data_size,fp);
        }
        return true;
    }
private:
    int _binary_search(source_type target)
    {
        int l = 0,r = (int)m_data.size() - 1,mid;
        while(l<=r)
        {
            mid = (l + r) / 2;
            if(m_data[l].m_index == target.m_index)
            {
                return l;
            }
            if(m_data[r].m_index == target.m_index)
            {
                return r;
            }
            if(m_data[mid].m_index == target.m_index)
            {
                return mid;
            }
            if(m_data[mid].m_index > target.m_index)
            {
                r = mid - 1;
            }
            else
            {
                l = mid + 1;
            }
        }
        return -1;
    }
    public:
    vector<source_type> m_data;
};

template<typename source_type>
class UniqueSource
{
public:
    UniqueSource(){}
    ~UniqueSource(){}
    bool Add(const source_type& other)//return false when insert failed,otherwise return true
    {
        if(m_map_source_to_index.find(other) == m_map_source_to_index.end())
        {
            int map_size = m_map_source_to_index.size();
            m_data.push_back(other);
            m_map_source_to_index.insert(pair<source_type,int>(other,map_size));
            m_result.push_back(map_size);
            return true;
        }
        else
        {
            m_result.push_back(m_map_source_to_index[other]);
            return true;
        }
        return false;
    }

    bool Delete(int elemIndex)  // delete the elem by elem Index,If succeed ,return true,otherwise return false
    {
        if(elemIndex < 0)
            return false;
        if(elemIndex >= m_data.size())
            return false;
        typename std::map<source_type,int>::iterator mit;
        typename std::vector<source_type>::iterator vit;
        for(mit = m_map_source_to_index.begin();mit!=m_map_source_to_index.end();++mit)
        {
            m_map_source_to_index.erase(mit);
        }
        vit = m_data.begin() + elemIndex;
        m_data.erase(vit);
        return true;
    }

    bool Clear()
    {
        m_map_source_to_index.clear();
        m_data.clear();
        m_result.clear();
        return true;
    }

    bool WriteFile(FILE*& fp)
    {
        if(fp == nullptr)
            return false;
        bool result = write_int(m_data.size(),fp);
        if(result == false)
            return false;
        if(m_data.size() > 0)
            fwrite(&(m_data[0]),sizeof(source_type),m_data.size(),fp);
        result = write_int(m_result.size(),fp);
        if(result == false)
            return false;
        if(m_result.size() > 0)
            fwrite(&(m_result[0]),sizeof(int),m_result.size(),fp);
        return true;
    }

    bool ReadFile(FILE*& fp)
    {
        if(fp == nullptr)
            return false;
        Clear();
        int data_size;
        read_int(data_size,fp);
        if(data_size > 0)
        {
            printf("[%d]",data_size);
            m_data.resize(data_size);   /////////////////Crash!!!!!!!!!!!!
            printf("Resize Ok\r\n");
            fread(&(m_data[0]),sizeof(source_type),data_size,fp);
        }
        read_int(data_size,fp);
        printf("[%d]",data_size);
        if(data_size > 0)
        {
            m_result.resize(data_size);
            fread(&(m_result[0]),sizeof(int),data_size,fp);
        }
        return true;
    }
//private:
    map<source_type,int> m_map_source_to_index;
    vector<source_type> m_data;
    vector<int> m_result;   //the index I want
};

int main()
{
    UniqueSource<SANOBJ> m;
    SANOBJ t = {"123","456"};
    m.Add(t);
    printf("Added\r\n");
    FILE* fp = nullptr;
    fp = fopen("test.b","wb");
    if(fp == nullptr)
    {
        printf("Failed...\r\n");
    }
    bool ret = false;
    ret = m.WriteFile(fp);
    if(ret)
    {
        printf("Writed!\r\n");
        fclose(fp);
    }
    fp = fopen("test.b","rb");
    if(fp == nullptr)
    {
        printf("Failed...\r\n");
    }
    ret = m.ReadFile(fp);
    fclose(fp);
    printf("Readed\r\n");
    for(int i=0;i<m.m_data.size();i++)
        printf("%s %s\r\n",m.m_data[i].path,m.m_data[i].nickname);
    return 0;
}

3 个答案:

答案 0 :(得分:0)

是。问题在于* this = {}

如果我是你,我会像这样重写SANOBJ构造函数(这是一个粗略的代码,如果你愿意,你可能需要稍微修改它)

SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
{
    if (( _p != nullptr ) && ((strlen(_p) < 128)))
        strcpy(path,_p);

    if (( _n != nullptr ) && ((strlen(_n) < 40)))
        strcpy(nickname,_n);
}

它将解决问题。

当然,我不玩*这个(不是这个)。

答案 1 :(得分:0)

*this = {}默认构造新的SANOBJ实例,然后将其分配给*this。这通常没问题,但是你在这里从SANOBJ默认构造函数调用它(使逻辑类似于&#34;默认构造一个SANOBJ,默认构造一个{{1}然后将其值赋给我自己&#34;),导致无限递归并最终导致堆栈溢出。

旁注:不需要复制构造函数。

答案 2 :(得分:0)

如果你想确保成员变量为空(char path [128]和char nickname [40]) 在构造函数的开头设置类似于: path[0] = '\0'; nickname[0] = '\0'; 或者在构造函数上使用类似的东西:

SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
    : path(), nickname()
{

}

但请勿使用*this= {}