std::map mit operator>> Überladung füllen



  • Hi Leute,
    ich versuche grade /proc/meminfo zu parsen und in einer std::map zu speichern.

    Das ganze klappt auch schon sehr gut allerdings bekomme ich immer Conditional jumps und uninitialised value of size 8 Fehler.(Ich denke die genauen Fehler muss ich nicht posten, wenn aber doch gewünscht mach ich das gerne) Debugging mache ich mit valgrind. Ich beschäftige mich seit gestern mit diesem Fehler und weiß nicht weiter. Aber zum Code:

    std::istream& operator>>(std::istream& in, std::map<std::string, long>& my_map){
      std::string tmp;
      long tmp2;
      in >> tmp >> tmp2;
      tmp.back() = '\0'; //überschreiben der ':' 
      my_map[tmp] = tmp2;
      return in.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); //damit kB nicht mitgenommen wird und ignoriert wird
    }
    
    bool RamInfo::ParseMemInfo(){
      std::ifstream meminfo("/proc/meminfo");
      if (!meminfo.is_open()) {
        return false;
      }
    
      for(;meminfo >> FullMemInfo;); //geht das schöner? Da wusste ich es nicht besser. :/
    
      for (auto it = FullMemInfo.begin(); it != FullMemInfo.end(); ++it) {
        std::cerr << it->first << " " << it->second << '\n';
      }
      return true;
    }
    

    Und hier mein privater Member:

    private:
        std::map<std::string, long> FullMemInfo;
    

    Input:

    MemTotal:        8169336 kB
    MemFree:         2155128 kB
    Buffers:          263032 kB
    Cached:          2290392 kB
    SwapCached:            0 kB
    Active:          3759544 kB
    Inactive:        1739936 kB
    Active(anon):    2947964 kB
    Inactive(anon):    41468 kB
    Active(file):     811580 kB
    Inactive(file):  1698468 kB
    Unevictable:           0 kB
    Mlocked:               0 kB
    SwapTotal:             0 kB
    SwapFree:              0 kB
    Dirty:              4360 kB
    Writeback:             0 kB
    AnonPages:       2946100 kB
    Mapped:           486200 kB
    Shmem:             43380 kB
    Slab:             268620 kB
    SReclaimable:     216832 kB
    SUnreclaim:        51788 kB
    KernelStack:        5736 kB
    PageTables:        62964 kB
    NFS_Unstable:          0 kB
    Bounce:                0 kB
    WritebackTmp:          0 kB
    CommitLimit:     4084668 kB
    Committed_AS:    7108248 kB
    VmallocTotal:   34359738367 kB
    VmallocUsed:      324688 kB
    VmallocChunk:   34359410300 kB
    HardwareCorrupted:     0 kB
    AnonHugePages:         0 kB
    HugePages_Total:       0
    HugePages_Free:        0
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    Hugepagesize:       2048 kB
    DirectMap4k:      233024 kB
    DirectMap2M:     8146944 kB
    

    Output(vor dem output kommen die Fehler d.h. es kommt vor der ausgaben Schleife die nur zum debuggen ist):

    Active 3789916
    Active(anon) 2976424
    Active(file) 813492
    AnonHugePages 0
    AnonPages 2974616
    Bounce 0
    Buffers 264300
    Cached 2294664
    CommitLimit 4084668
    Committed_AS 7193772
    DirectMap2M 8146944
    DirectMap4k 233024
    Dirty 536
    HardwareCorrupted 0
    HugePages_Free 0
    HugePages_Rsvd 0
    HugePages_Surp 0
    HugePages_Total 0
    Hugepagesize 2048
    Inactive 1743636
    Inactive(anon) 44560
    Inactive(file) 1699076
    KernelStack 5720
    Mapped 490884
    MemFree 2120860
    MemTotal 8169336
    Mlocked 0
    NFS_Unstable 0
    PageTables 63004
    SReclaimable 217136
    SUnreclaim 51036
    Shmem 46472
    Slab 268172
    SwapCached 0
    SwapFree 0
    SwapTotal 0
    Unevictable 0
    VmallocChunk 34359410300
    VmallocTotal 34359738367
    VmallocUsed 324688
    Writeback 0
    WritebackTmp 0
    


  • Da sind so spontan 2 Dinge, die mir auffallen.

    Wenn "in >> tmp" fehl schlägt, dann ist tmp leer und "tmp.back()" liefert nichts sinnvolles.

    Ausserdem ist der std::string kein null-Terminierter String. Er kann durchaus auch das Zeichen '\0' enthalten. Wenn Du das letzte Zeichen auf '\0' setzt, dann tust Du genau das. In C-Strings erwartet man, dass sich die länge des Strings um 1 verkürzt. Aber das ist nicht so bei std::string.



  • tntnet schrieb:

    Da sind so spontan 2 Dinge, die mir auffallen.

    Wenn "in >> tmp" fehl schlägt, dann ist tmp leer und "tmp.back()" liefert nichts sinnvolles.

    Ausserdem ist der std::string kein null-Terminierter String. Er kann durchaus auch das Zeichen '\0' enthalten. Wenn Du das letzte Zeichen auf '\0' setzt, dann tust Du genau das. In C-Strings erwartet man, dass sich die länge des Strings um 1 verkürzt. Aber das ist nicht so bei std::string.

    Danke für die Hinweise!
    So besser:

    if (tmp.length() != 0) {
        tmp.erase(tmp.length()-1);
      } else {
        return in;
      }
    


  • Es klappt nach dem ich in der Zeile 16 folgendes geändert habe:

    for(;meminfo >> FullMemInfo;){}
    

    Davor ist er immer zu weit gelaufen und damit in undefinierten bereich. Allerdings verstehe ich nicht ganz den Unterschied. Falls jemand ein paar Worte dazu sagen will immer gerne! 😃
    Ansonsten auch gerne Anregungen oder Verbesserungen erwünscht.
    Danke!



  • Fuchs aus dem Wald schrieb:

    So besser:

    if (tmp.length() != 0) {
        tmp.erase(tmp.length()-1);
      } else {
        return in;
      }
    

    Sieht auf dem ersten Blick merkwürdig aus. Im Kontext ist das zwar dann richtig aber ich würde es nicht so formulieren. Es ist nicht leicht ersichtlich, dass es nach dem erase dann wieder nach dem if weiter geht.

    Besser wäre:

    if (tmp.empty())
      return in;
    
    tmp.erase(tmp.length()-1);
    

    Das sieht man eher, was hier passiert. Und in C++11 gibt es auch ein "tmp.pop_back()".



  • Fuchs aus dem Wald schrieb:

    Es klappt nach dem ich in der Zeile 16 folgendes geändert habe:

    for(;meminfo >> FullMemInfo;){}
    

    Davor ist er immer zu weit gelaufen und damit in undefinierten bereich. Allerdings verstehe ich nicht ganz den Unterschied. Falls jemand ein paar Worte dazu sagen will immer gerne! 😃
    Ansonsten auch gerne Anregungen oder Verbesserungen erwünscht.
    Danke!

    Das kann nicht das Problem gewesen sein. Ein {} ist hier das gleiche wie ein Semikolon. Aber auch hier nochmal der Hinweis, dass man das lesbarer gestalten kann. Der leere Schleifenrumpf ist sehr versteckt. Ich würde ihm auf jeden Fall in eine eigene Zeile spendieren. Und while geht hier auch:

    while (meminfo >> FullMemInfo)
      ;
    


  • tntnet schrieb:

    Besser wäre:

    if (tmp.empty())
      return in;
    
    tmp.erase(tmp.length()-1);
    

    Das sieht man eher, was hier passiert. Und in C++11 gibt es auch ein "tmp.pop_back()".

    Ich muss sagen du hast recht, danke dafür! Allerdings will das tmp.pop_back nicht obwohl:

    g++ -std=c++0x
    

    Naja klappt ja auch mit tmp.erase(...).

    tntnet schrieb:

    while (meminfo >> FullMemInfo)
      ;
    

    Auch das sehe ich ein. 🙂 Deswegen hab ich ja noch mal gefragt ob es schöner geht.
    Würdest du das Semikolon wirklich in die nächste Zeile machen?



  • Auch das sehe ich ein. Deswegen hab ich ja noch mal gefragt ob es schöner geht.
    Würdest du das Semikolon wirklich in die nächste Zeile machen?

    Definitiv ja! Dann sieht man sofort, was mit der Schleife gemeint ist. Wenn es am Ende der Zeile steht könnte es ein Flüchtigkeitsfehler gewesen sein.



  • Ok vielen danke an alle!


Log in to reply