首页 文章

const char *在c中的std :: map中重复数据

提问于
浏览
-3

我有一个罕见的问题 .

我已经将一个结构存储到std :: map中,插入了第一个数据并正常运行,但是当我尝试存储多个结构数据时,所有 const char* 的所有 const char* 值都在结构内部丢失并被替换用新数据 .

我恢复了代码:

struct Emitter{

.
.
const char * name;
const char * file;
} 

Emitter metadata;

在我插入结构之前,我填充const char *变量whit这段代码(我得到的信息是一个XML)

std::string name_tmp= atts.getString("name", "ed");
char tmp[50];
strcpy(tmp, name_tmp.c_str());
metadata.name= tmp;

std::string file_tmp= atts.getString("file", "ed");
char tmp2[50];
strcpy(tmp2, file_tmp.c_str());
metadata.file= tmp2;

Map 的关键是Emitter结构中的名称;

typedef std::map<std::string, Emitter> Dictionary;
typedef std::pair<std::string, Emitter> Defination;

Dictionary::iterator it = map.find(name);

        if (it != map.end())
            map[metadata.name] = data;
        else{

            if (map.size() == 0) 
                map.insert(Defination(metadata.name, metadata));
            else{
                ParticlesDictionary::iterator i = map.begin();
                map.insert(i, Defination(metadata.name, metadata));
            }
        }

当我打印插入堆栈输出的过程时,我得到这个:

// key ---> struct value (name) ---> struct value (file)

//first time
  key1 --> eddy --> fileName1

//second time
  key1 --> eddy1-->fileName2
  key2 --> eddy1-->fileName2

//third time

  key1 --> eddy2-->fileName3
  key2 --> eddy2-->fileName3
  key3 --> eddy2-->fileName3

为什么会这样?

请帮忙

2 回答

  • 0

    您的 const char* 字段指向不属于 struct 的缓冲区 . 这意味着当数组 tmptmp2 超出范围时,它们使用的空间可用于其他数据 .

    在你的情况下,它被重用于下一个 struct . 要解决此问题,您应该分配 struct 拥有的内存:将 const char* 字段替换为 std::string 字段,或者使用 newdelete .

  • 0

    无论你是在问SO还是试图自己解决这样的问题,第一步是 Build 一个MVCE或SSCE - 一个小的,不连续的问题再现 .

    使用您的代码,这将使我们关注以下内容:

    #include <iostream>
    
    struct A {
        const char* text;
    };
    
    void f(A& a, const char* text) {
        char localTxt[50];
        strcpy(lt, text);
        a.text = localTxt;
    }
    
    int main() {
        A a, b;
        f(a, "hello");
        f(b, "world");
        std::cout << "But afterwards:" << std::endl;
        std::cout << "a = " << a.text << ", b = " << b.text << "\n";   
    }
    

    我们已经放弃了你在这里所做的大部分工作,并且在“将这个值放入结构中时会发生什么”中进行了磨练 .

    这里的问题是 localText 存在于堆栈中,我们将其地址放入结构中 . 指针是包含地址的数值 . 当我们这样做时,没有什么神奇的事情发生:

    char a[] = "hello";
    char* b = a;
    

    b 现在指向 a ,仍然只有一个字符串副本 .

    同时,整个代码块似乎可能导致这种问题 . 这样做会不会让您的生活变得更加简单:

    class Emitter {
        std::string name, file;
    };
    
    void myFunc() {
         metadata.name = atts.getString("name", "ed");
         metadata.file = atts.getString("file", "ed");
    }
    

    如果这对您不起作用,您可能需要考虑:

    const std::string& name = atts.getString("name", "ed");
    metadata.name = new char[] (name.length() + 1); // +1 for \0
    std::copy(metadata.name, name.c_str());
    

    但请注意,您现在负责记忆:

    class Emitter {
        const char* name;
        const char* file;
    
        Emitter() : name(nullptr), file(nullptr) {}
        ~Emitter() {
            if (name)
                delete [] name;
            if (file)
                delete [] file;
        }
        // ...
    };
    

相关问题