[C++] g ++ erzeugt segfault mit normaler Kompilierung, aber keine mit -g



Answers

Sie rufen fast sicher undefined Verhalten (UB) irgendwo in Ihrem Programm auf. Der Punkt von UB ist, dass das Verhalten nicht nur undefiniert ist, sondern sich je nach Plattform, Compiler, Flags usw. ändern kann. Das Hinzufügen von -g ist vermutlich eine Störung, um den Segfault zu vermeiden, aber das ist nur Zufall.

Question

Ich lerne gerade C ++ mit Bruce Eckels "Thinking in C ++" und ich bin in den ersten Kapiteln. Ich habe einen C- und Java-Hintergrund. Im Moment habe ich folgendes Problem: Wenn ich die Quellen unten mit kompiliere

g++ A.cpp B.cpp bmain.cpp

, das Programm gibt eine "1" (korrekt) und dann einen segfault aus. Wenn ich mit kompiliere

g++ -g A.cpp B.cpp bmain.cpp

, das exakt gleiche Programm erzeugt einen 1 und NO-Fehler! Ich muss sagen, ich finde das erstaunlich. Könnte jemand darauf hinweisen, was ich falsch mache? Mein Betriebssystem ist "Linux 2.6.35-30-generic # 54-Ubuntu x86_64", mein g ++ ist Version "g ++ (Ubuntu / Linaro 4.4.4-14ubuntu5) 4.4.5".

EDIT: Nur weil dies eine wichtige Quelle des Fehlers zu sein scheint, danke @Evan Teran: Der A-Konstruktor in der B-Struktur wird nie aufgerufen! Ich habe einen "cout <<" blah "<< endl;" innen und es druckt nichts

EDIT: Ich habe jetzt die "Return 0" am Ende von main, aber das hilft nicht.

Ah:

#ifndef A_H
#define A_H

#include <string>

class A {
public:
        int i;
        std::string str;
        void print();
        A();
};

#endif

A.cpp:

#include "A.h"
#include <iostream>
#include <string>

using namespace std;

void A::print() {
        cout << str << " " << i << endl;
}

A::A() {
        str = "initstr";
    i = 0;
}

Bh:

#ifndef B_H
#define B_H

#include "A.h"

class B {
private:
        int counter;
public:
        A a;
        B();
        void increase();
        int read();
};

#endif

B.cpp:

#include "B.h"

using namespace std;

B::B() {
        counter = 0;
}

void B::increase() {
        ++counter;
}

int B::read() {
        return counter;
}

bmain.cpp:

#include <iostream>
#include "B.h"

using namespace std;

int main(int argc, char **argv) {
        B b;
        b.increase();
        cout << b.read() << endl;
        return 0;
}

EDIT: Ich habe g ++ von den Paketen installiert. Mein Ubuntu ist auch sehr Standard.

Das ist, was ich bekomme, wenn ich gdb a.out core rufe

warning: Can't read pathname for load map: Eingabe-/Ausgabefehler.
Reading symbols from /usr/lib/libstdc++.so.6...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libstdc++.so.6
Reading symbols from /lib/libm.so.6...Reading symbols from /usr/lib/debug/lib/libm-2.12.1.so...done.
done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.12.1.so...done.
done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.12.1.so...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0  0x00007fba1049104b in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/libstdc++.so.6

EDIT 2: BTW, meine Hardware ist meines Wissens nicht fehlerhaft und ich behandle das OS sehr gut

EDIT 3: Valgrind meldet Folgendes:

==3428== Conditional jump or move depends on uninitialised value(s)
==3428==    at 0x4ECB022: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/libstdc++.so.6.0.14)
==3428==    by 0x400D73: A::~A() (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==    by 0x400D91: B::~B() (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==    by 0x400CD7: main (in /home/xxx/C++/Exercises/ch04/a.out)
==3428== 
==3428== Use of uninitialised value of size 8
==3428==    at 0x4ECB04B: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/libstdc++.so.6.0.14)
==3428==    by 0x400D73: A::~A() (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==    by 0x400D91: B::~B() (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==    by 0x400CD7: main (in /home/xxx/C++/Exercises/ch04/a.out)
==3428== 
==3428== Invalid read of size 4
==3428==    at 0x4ECB04B: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/libstdc++.so.6.0.14)
==3428==    by 0x400D73: A::~A() (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==    by 0x400D91: B::~B() (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==    by 0x400CD7: main (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==  Address 0xfffffffffffffff8 is not stack'd, malloc'd or (recently) free'd
==3428== 
==3428== 
==3428== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==3428==  Access not within mapped region at address 0xFFFFFFFFFFFFFFF8
==3428==    at 0x4ECB04B: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/libstdc++.so.6.0.14)
==3428==    by 0x400D73: A::~A() (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==    by 0x400D91: B::~B() (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==    by 0x400CD7: main (in /home/xxx/C++/Exercises/ch04/a.out)
==3428==  If you believe this happened as a result of a stack
==3428==  overflow in your program's main thread (unlikely but
==3428==  possible), you can try to increase the size of the
==3428==  main thread stack using the --main-stacksize= flag.
==3428==  The main thread stack size used in this run was 8388608.
==3428== 
==3428== HEAP SUMMARY:
==3428==     in use at exit: 0 bytes in 0 blocks
==3428==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3428== 
==3428== All heap blocks were freed -- no leaks are possible    





Links