带有map C++程序没有提供与上次存储相同的资源

C++ program with map is not giving same resutls as it stored last time

本文关键字:存储 资源 C++ map 程序 带有      更新时间:2023-10-16

我有以下程序,它在map中存储四个字符串并首次打印。现在它运行另一个时间来检索存储的值。但第二次结果与第一次结果不同。

#include <map>
using namespace std;
void fun_call(void **,char * );
main(){
        void *data=NULL;
        char value[100];
        int i=0,j=0;
        char key[][10]={"disk1","disk2","disk3","disk4"};
        cout << "printing all mapped values " << endl ;
        data = (void *) malloc( 100);
        for(j=0;j<2;j++){
        for(i=0;i<4;i++){
                fun_call(&data,key[i]);
                memcpy(value,data,100);
                cout << "key ="<<key[i]<<" value is " << value << endl;
        }
        cout <<"====================="<< endl;
        }
}
void fun_call(void **tmp,char name[10])
{
        void *tmp_data;
        char str[100]="ravindra";
        int len =0;
        static std::map<std::string,void *> name_data_map;
        std::map<std::string,void *>::iterator iter   ;
        iter=name_data_map.find(name) ;
        if ( iter == name_data_map.end())
        {
                len=strlen(str)+strlen(name)+1;
                tmp_data = (void *) malloc ( len );
                strcat(str,name);
                memcpy(tmp_data,str,len);
                name_data_map[name]=tmp_data;
                cout << "Inside the if" << endl ;
        }
        else
                cout << "disk pos "<< iter->first << endl;
        cout << "Outside the if" << endl ;
        iter=name_data_map.find(name) ;
        memcpy(*tmp,iter->second,len);
}

输出:

$ ./a.out打印所有映射值在如果在如果之外键 =磁盘 1 值是 Ravindradisk1在如果在如果之外键 =磁盘 2 值是 Ravindradisk2在如果在如果之外键 =磁盘 3 值是 Ravindradisk3在如果在如果之外键 =磁盘 4 值是 Ravindradisk4=====================磁盘 POS 磁盘 1在如果之外键 =磁盘 1 值是 Ravindradisk4磁盘 POS 磁盘2在如果之外键 =磁盘 2 值是 Ravindradisk4磁盘 POS 磁盘3在如果之外键 =磁盘3 值是 Ravindradisk4磁盘 POS 磁盘4在如果之外键 =磁盘 4 值是 Ravindradisk4

知道为什么第二次迭代将所有数据都作为:"Ravindradisk4"

lenfun_call开头设置为 0,

所以如果在第二次运行中它没有进入你的ifmemcpy最后复制 0 字节。因此,无论key如何,第一次迭代中main()的最后一个value都保持不变。

你的代码有很多问题,如果它是一个有效的(或远程习惯的)C++程序。

正如@starbugs指出的那样,您第二次没有使用正确的长度来复制结果。 一行"修复"将是更改:

memcpy(*tmp,iter->second,len);

。自:

memcpy(*tmp,iter->second,strlen((char*)iter->second)+1);

对于为什么脆性 C 字符串技术最好用C++方法代替的一些基础知识,我想向人们展示以下内容:

学习标准C++作为一门新语言 (PDF) by Bjarne

一旦你掌握了你可能更能接受C++和标准库应该使用的精神。

您的程序是如此琐碎,以至于很容易展示如何简化它以生成更健壮且易于阅读的惯用代码:

#include <map>
#include <iostream>
#include <string>
using namespace std;
string fun_call(string name)
{
    static map<string,string> name_data_map;
    map<string,string>::iterator iter;
    iter = name_data_map.find(name);
    if (iter == name_data_map.end()) {
        string mapvalue = "ravindra";
        mapvalue += name;
        name_data_map[name] = mapvalue;
        cout << "Inside the if" << endl ;
    }
    else
        cout << "disk pos "<< iter->first << endl;
    cout << "Outside the if" << endl;
    iter = name_data_map.find(name) ;
    return iter->second;
}
int main() {
    string keys[] = {"disk1","disk2","disk3","disk4"};
    cout << "printing all mapped values " << endl ;
    for(int j = 0; j < 2; j++) {
        for(int i = 0; i < 4; i++){
            string value = fun_call(keys[i]);
            cout << "key =" << keys[i] <<" value is " << value << endl;
        }
        cout << "=====================" << endl;
    }
}

我将停止提供一个具有相同输出和控制流的基本等效程序。

笔记:

  • 在标准C++中,main 必须有一个 int 作为返回类型(尽管它不需要参数或 return 语句,奇怪的是)

  • using namespace std;行使您不必在标准库类(如字符串、map 及其迭代器)前面键入 std::。 但是不要把它放在头文件中,因为它可能会导致包含它们的其他源文件出现问题,并且有自己的定义,如果不消除歧义,这些定义可能会与标准名称冲突。

  • 如果使用标准库,则值类型在后台进行内存管理,并且它们使用的内存在类内分配并在析构函数中释放。 如果您需要执行显式内存管理,请使用 new 和 delete。

首先,一般来说,C++考虑使用 new/delete 而不是 malloc()/free() .

我不确定你到底想完成什么(即为什么你不断地复制值),但你没有设置长度,所以memcpy()不会复制任何东西。

解决此问题的另一个简单方法是使用存储在iter->second中的指针(请注意,您可以修改data并更新该映射条目 - 所以也许这不是您想要的)。

例如,不要在 main 中为 data 变量分配内存,只需更改此行

memcpy(*tmp, iter->second, len);

*tmp = iter->second;

现在,main 中 data 的指针地址设置为存储在地图中的指针地址。

首先,我什至不确定你的代码是如何编译的。您的主函数缺少返回类型,void/不返回只是不好的做法。重构它以适应简单的返回 0 并使其返回类型int

此外,在编译之前缺少几个包含(即 iostream 和字符串)。不要使用 using namespace std ,尝试仅从 std 命名空间中"提取"您需要的内容。一般来说,将其全部引入是一种潜在的危险和不良做法,因为将来您可能会遇到命名约定冲突(这将带来很多麻烦)。

回到手头的问题。如果你不是在试验/惩罚你的思想,你就会在这里应用一些非常糟糕的做法。如此多的内存复制和指针移动,即使在我处理移动顶点缓冲区时,我也无法完成。并将您的分配与释放分配相匹配,这是一些非常糟糕的内存管理。在C++中,我们使用new/delete。

由于您要将指针的地址传递给数据变量,因此只需使用 *tmp 修改数据的指针即可。

由于您的name_data_map是静态的,因此它可以在循环中幸存下来。因此,iter的第二个数据成员是指向当前数据对象的实际指针。只需更改第二个函数的最后一行代码:

*tmp = iter->second;

无论如何,这是我的两分钱...我什至不明白你想做什么。祝你好运!