Microsoft C ++异常处于未处理的异常:内存位置的{std :: bad_alloc

时间:2017-12-12 20:30:28

标签: c++ exception unhandled-exception

我有一个大的向量(mainvect)的struct info对象(大约8百万元素),我想删除重复项,结构由pid和uid组成。

 struct info
 {
    int pid;
    string uid;

 }

我有另一个向量( vect1 ),其中包含每个pid的信息及其在mainvect中的出现(其搜索特定索引的帮助并非所有主要vect)vect1的大小为420k元素

struct pidInfo
 {
    int pid;
    int numofoccurence;
}

我想在 vect2 中将unqiue元素存储在mainvect中。

 .
 .
// sort mainvect based on pid
sort(mainvect.begin(), mainvect.end(), sortByPId());

int start = 0;
int end = 0;
vector <string> temp;  // to store uids with a specific pid 

for (int i = 0; i < vect1.size(); i++)
{
   end = end + vect1[i].numofoccurence;

    for (int j = start; j < end; j++)
    {
        temp.push_back(mainvect[j].uid);
    }

    start = start + vect1[i].numofoccurence;

    // remove duplicate uid 
    sort(temp.begin(), temp.end());
    temp.erase(unique(temp.begin(), temp.end()), temp.end());

    // push remaining unique uids 
    for (int k = 0; k < temp.size(); k++)
    {
        info obb;
        obb.pid = vect1[i].pid;
        obb.uid = temp[k];
        vect2.push_back(obb);
    }

    // empty the temp vector to use in next i iteration
    temp.erase(temp.begin(), temp.end());

}
 .
 .

但是当我运行代码时,它给了我异常,如下图所示 enter image description here

3 个答案:

答案 0 :(得分:3)

你的内存不足。你可以做的事情很少:

  1. 您正在Windows上构建32位程序。这意味着您只有2 GB的RAM,可以考虑机器上有多少物理内存。您应该为64位体系结构构建程序,以便访问您拥有的所有RAM。为此,您需要为平台设置为x64的项目创建新配置。
  2. 你应该更聪明地使用你的记忆。您可以做的最快的事情是将std::vector替换为std::dequeu以获取大型向量。
  3. std::vector的问题在于,每次增长时都会分配一个新的内存块并复制所有数据。您正在使用的MSVC实现每次增长1.5倍。因此,如果向量占用1 GB的内存,下次调整大小时,它将尝试分配1.5 GB,在调整大小时正在进行2.5 GB的RAM。

    std::deque的实现通常会在较小的块中分配内存,因此调整大小的问题会更少。

    你需要注意的另一件事是std::string。 MSVC实现使用SSO (Small-String-Optimization)Every instance of std :: string` afair在x86上占用32个字节。因此,你的800万元素向量中的每个元素都可能会或可能不会浪费这些记忆。

    根据您希望在计划上花费的时间,您可能想了解memory-mapped files

答案 1 :(得分:3)

我认为你确实有算法问题。在每次迭代中,您要排序并在temp向量中仅保留唯一元素。但是使用这种方法,每次迭代都会在vect2中添加越来越多的重复项。因此,您应该在vect2中排序并仅保留唯一元素。实际上,利用std::set代替tempvect2可能会更好。

另一个建议是如果它具有某种修复长度格式(如GUID),则可以为uid使用更好的存储。

答案 2 :(得分:1)

如上所述,您的内存不足。如果你真的有这么多元素,那么研究一个像sqlite这样的小型数据库可能是一个明智的想法。

但是由于问题是关于C ++标准容器,所以你正在接近这个问题。你正在做许多不必要的排序和循环。不仅充满了bug,你的算法至少是O(n ^ 3)

为什么不使用已经排序的容器之一,例如std :: map?您可以像这样重复列出一个列表:

std::vector<info> input;

// copy into map
std::map<int, info> tmp;
for (info& i : mainvect) {
  tmp[i.pid] = i;
}

// copy back out
std::vector<info> output(tmp.size());
std::transform(tmp.begin(), tmp.end(), output.begin(), [] (const std::pair<int, info>& p) {
    return p.second;
});

代码不仅更清晰,而且运行在O(n + ln(n))。或者,跳过第二步,首先使用std :: map或std :: set作为数据。

此外,如果你处理大量的物品,你也不想使用std :: vector。关键问题是向量的内存需要是一块连续的内存。您可能想要使用双端队列或列表。