Newbie: bus error

Discussion in 'C++' started by David Kensche, Oct 12, 2004.

  1. Hello,
    A bus error is caused every time I execute a method. I learned that bus
    errors are usually caused if something is going wrong with memory
    allocation and dereferencing. But I can't make out the error here.
    Can anybody help?

    Thanks beforehand,
    David Kensche



    int pc_record(char* key1, char* key2, record_t record) {
    //cout << "pc_record(..): record = " << (int)record << "\n";
    Logger *log = new Logger("TermCache.log");
    string msg = "pc_record(";
    // By the way, this is not very convenient, is there a way to ease
    // this setup?
    msg += key1;
    msg += ", ";
    msg += key2;
    msg += "): ";
    //msg = "pc_record(" + ", " + "): ";
    //msg += string(key1) + ", " + string(key2) + "): ";
    //msg += key1 + ", " + key2 + "): ";
    // The following line causes the bus error.
    log->debug(msg + "entered");
    int solve = FAIL;
    recordMap* cluster = &clusters[key2];
    if(cluster->find(key1) == cluster->end()) {
    cluster->insert(recordMap::value_type(key1, record));
    solve = SUCCEED;
    }

    delete log;
    return solve;
    }


    And this is the Logger class:
    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <string>
    using namespace std;

    #define TRACE 0
    #define DEBUG 1
    #define INFO 2
    #define WARN 3
    #define FATAL 4

    class Logger {

    char* logfile;
    int level;

    public:
    Logger(const char* file) {
    level = TRACE;
    logfile = (char*)malloc(strlen(getenv("HOME")) + 1 + strlen(file));
    //free(logfile);
    strcpy(logfile, getenv("HOME"));
    strcat(logfile, "/");
    strcat(logfile, file);
    }

    void setLevel(int logLevel) {
    level = logLevel;
    }

    void trace(string msg) {
    if(level <= TRACE) {
    std::eek:fstream out;
    out.open(logfile, ios_base::eek:ut | ios_base::app);
    out << "TRACE:" << msg << "\n";
    out.close();
    }
    }

    void debug(string msg) {
    if(level <= DEBUG) {
    std::eek:fstream out;
    out.open(logfile, ios_base::eek:ut | ios_base::app);
    out << "DEBUG:" << msg << "\n";
    out.close();
    }
    }

    void info(string msg) {
    if(level <= INFO) {
    std::eek:fstream out;
    out.open(logfile, ios_base::eek:ut | ios_base::app);
    out << "INFO:" << msg << "\n";
    out.close();
    }
    }

    void warn(string msg) {
    if(level <= WARN) {
    std::eek:fstream out;
    out.open(logfile, ios_base::eek:ut | ios_base::app);
    out << "WARN:" << msg << "\n";
    out.close();
    }
    }

    void fatal(string msg) {
    if(level <= FATAL) {
    std::eek:fstream out;
    out.open(logfile, ios_base::eek:ut | ios_base::app);
    out << "FATAL:" << msg << "\n";
    out.close();
    }
    }

    private:
    void operator=(const Logger&);
    void operator&();
    void operator,(const Logger&);
    };
     
    David Kensche, Oct 12, 2004
    #1
    1. Advertising

  2. "David Kensche" <-aachen.de> wrote in message
    news:...
    > Hello,
    > A bus error is caused every time I execute a method. I learned that bus
    > errors are usually caused if something is going wrong with memory
    > allocation and dereferencing. But I can't make out the error here.
    > Can anybody help?


    See below.

    >
    > Thanks beforehand,
    > David Kensche
    >
    >
    >
    > int pc_record(char* key1, char* key2, record_t record) {
    > //cout << "pc_record(..): record = " << (int)record << "\n";
    > Logger *log = new Logger("TermCache.log");
    > string msg = "pc_record(";
    > // By the way, this is not very convenient, is there a way to ease
    > // this setup?
    > msg += key1;
    > msg += ", ";
    > msg += key2;
    > msg += "): ";
    > //msg = "pc_record(" + ", " + "): ";
    > //msg += string(key1) + ", " + string(key2) + "): ";
    > //msg += key1 + ", " + key2 + "): ";


    This is perhaps a bit easier (and clearer)

    ostringstream buffer;
    buffer << "pc_record(" << key1 << ", " << key2 << "): ";
    string msg = buffer.str();

    > // The following line causes the bus error.
    > log->debug(msg + "entered");
    > int solve = FAIL;
    > recordMap* cluster = &clusters[key2];
    > if(cluster->find(key1) == cluster->end()) {
    > cluster->insert(recordMap::value_type(key1, record));
    > solve = SUCCEED;
    > }
    >
    > delete log;
    > return solve;
    > }
    >
    >
    > And this is the Logger class:
    > #include <iostream>
    > #include <fstream>
    > #include <cstdlib>
    > #include <string>
    > using namespace std;
    >
    > #define TRACE 0
    > #define DEBUG 1
    > #define INFO 2
    > #define WARN 3
    > #define FATAL 4
    >
    > class Logger {
    >
    > char* logfile;
    > int level;
    >
    > public:
    > Logger(const char* file) {
    > level = TRACE;
    > logfile = (char*)malloc(strlen(getenv("HOME")) + 1 + strlen(file));
    > //free(logfile);
    > strcpy(logfile, getenv("HOME"));
    > strcat(logfile, "/");
    > strcat(logfile, file);
    > }


    One error is here, you need to malloc one more byte (length of HOME, length
    of file, length of "/", plus one for terminating nul )

    logfile = (char*)malloc(strlen(getenv("HOME")) + 2 + strlen(file));

    And the moral is don't use C strings, use C++ strings.

    john
     
    John Harrison, Oct 12, 2004
    #2
    1. Advertising

  3. > This is perhaps a bit easier (and clearer)
    >
    > ostringstream buffer;
    > buffer << "pc_record(" << key1 << ", " << key2 << "): ";
    > string msg = buffer.str();
    >


    You need the header file <sstream> for the ostringstream class.

    john
     
    John Harrison, Oct 12, 2004
    #3
  4. David Kensche wrote:
    > Hello,
    > A bus error is caused every time I execute a method. I learned that bus
    > errors are usually caused if something is going wrong with memory
    > allocation and dereferencing. But I can't make out the error here.
    > Can anybody help?
    >
    > Thanks beforehand,
    > David Kensche
    >
    >
    >
    > int pc_record(char* key1, char* key2, record_t record) {


    Why 'key1' and 'key2' are not pointers to const char?

    > //cout << "pc_record(..): record = " << (int)record << "\n";
    > Logger *log = new Logger("TermCache.log");


    Why do you need 'log' dynamically allocated here? Why can't you just
    write

    Logger log("TermCache.log");

    ? No need to delete, no problems with dynamic memory...

    > string msg = "pc_record(";
    > // By the way, this is not very convenient, is there a way to ease
    > // this setup?


    What setup? What's not very convenient?

    > msg += key1;
    > msg += ", ";
    > msg += key2;
    > msg += "): ";
    > //msg = "pc_record(" + ", " + "): ";
    > //msg += string(key1) + ", " + string(key2) + "): ";
    > //msg += key1 + ", " + key2 + "): ";
    > // The following line causes the bus error.
    > log->debug(msg + "entered");
    > int solve = FAIL;
    > recordMap* cluster = &clusters[key2];
    > if(cluster->find(key1) == cluster->end()) {
    > cluster->insert(recordMap::value_type(key1, record));
    > solve = SUCCEED;
    > }
    >
    > delete log;
    > return solve;
    > }
    >
    >
    > And this is the Logger class:
    > #include <iostream>
    > #include <fstream>
    > #include <cstdlib>
    > #include <string>
    > using namespace std;
    >
    > #define TRACE 0
    > #define DEBUG 1
    > #define INFO 2
    > #define WARN 3
    > #define FATAL 4
    >
    > class Logger {
    >
    > char* logfile;


    Drop the 'char*', use std::string.

    > int level;
    >
    > public:
    > Logger(const char* file) {
    > level = TRACE;
    > logfile = (char*)malloc(strlen(getenv("HOME")) + 1 + strlen(file));
    > //free(logfile);
    > strcpy(logfile, getenv("HOME"));
    > strcat(logfile, "/");
    > strcat(logfile, file);


    Now, count the allocated characters. Where should the terminating \0 go?

    Once again, replace all the dynamic memory nonsense with std::string.
    You will be rid of all memory errors at once. Of course, you'll have
    to change _every_

    out.open(logfile,
    to
    out.open(logfile.c_str(),

    but is that such a big deal?

    > }
    >
    > void setLevel(int logLevel) {
    > level = logLevel;
    > }
    >
    > void trace(string msg) {
    > if(level <= TRACE) {
    > std::eek:fstream out;
    > out.open(logfile, ios_base::eek:ut | ios_base::app);


    'logfile' here is malformed.

    > out << "TRACE:" << msg << "\n";
    > out.close();
    > }
    > }
    >
    > void debug(string msg) {
    > if(level <= DEBUG) {
    > std::eek:fstream out;
    > out.open(logfile, ios_base::eek:ut | ios_base::app);


    'logfile' here is malformed.

    > out << "DEBUG:" << msg << "\n";
    > out.close();
    > }
    > }
    >
    > void info(string msg) {
    > if(level <= INFO) {
    > std::eek:fstream out;
    > out.open(logfile, ios_base::eek:ut | ios_base::app);


    'logfile' here is malformed.

    > out << "INFO:" << msg << "\n";
    > out.close();
    > }
    > }
    >
    > void warn(string msg) {
    > if(level <= WARN) {
    > std::eek:fstream out;
    > out.open(logfile, ios_base::eek:ut | ios_base::app);


    'logfile' here is malformed.

    > out << "WARN:" << msg << "\n";
    > out.close();
    > }
    > }
    >
    > void fatal(string msg) {
    > if(level <= FATAL) {
    > std::eek:fstream out;
    > out.open(logfile, ios_base::eek:ut | ios_base::app);


    'logfile' here is malformed.

    > out << "FATAL:" << msg << "\n";
    > out.close();
    > }
    > }
    >
    > private:
    > void operator=(const Logger&);
    > void operator&();
    > void operator,(const Logger&);
    > };
    >


    I don't understand why beginners can't help themselves and try to always
    use "new" or "malloc". Don't! There is no need for that in your program.

    Victor
     
    Victor Bazarov, Oct 12, 2004
    #4
  5. John and Victor have already pointed out problems in your code and gave
    you excellent advice. But there is another potential problem in your code:

    > class Logger {
    >
    > char* logfile;
    > int level;
    >
    > public:
    > Logger(const char* file) {
    > level = TRACE;
    > logfile = (char*)malloc(strlen(getenv("HOME")) + 1 + strlen(file



    If the HOME environment variable does not exist getenv() will return
    NULL. Nasty things can happen when you pass a NULL pointer to strlen().

    --
    Peter van Merkerk
    peter.van.merkerk(at)dse.nl
     
    Peter van Merkerk, Oct 12, 2004
    #5
  6. Thank you for all the hints, but it doesn't work yet.
    I replaced as much char* by string as I could, but to
    client modules (from C) this class has to look like C,
    and this is the reason why I need char* in the interface.
    The situation even worsened. Now I even do not need to
    create the Logger to cause a "bus error".
    My new source code looks like this:


    #include <map>
    #include <stdlib.h>
    #include <iostream>
    #include "TermCache.h"
    #include "prolog.h"
    #include "Logger.cc"
    using namespace std;

    typedef map<string, record_t> recordMap;
    typedef map<string, recordMap > clusterMap;

    class TermCache {
    clusterMap clusters;

    public:

    /**
    * Stores a copy of the PROLOG_TERM 'record' associated to
    * double key (key1, key2). Fails with an error if there
    * is already a value associated to the double key.
    */
    int pc_record(char* key1, char* key2, record_t record) {
    string k1 = string(key1);
    string k2 = string(key2);
    // As you can see now I have the Logger commented. But nevertheless
    // a bus error is caused by something.
    //Logger log(string("TermCache.log"));
    ostringstream buffer;
    buffer << "pc_record(" << k1 << ", " << k2 << "): ";
    string msg = buffer.str();
    //log.debug(msg + "entered");
    int solve = FAIL;
    recordMap* cluster = &clusters[k2];
    if(cluster->find(k1) == cluster->end()) {
    cluster->insert(recordMap::value_type(k1, record));
    solve = SUCCEED;
    }
    return solve;
    }

    /**
    * Stores a copy of the PROLOG_TERM 'record' associated to
    * double key (key1, key2). Any value that was associated
    * to the double key, is erased.
    */
    int pc_rerecord(char* key1, char* key2, record_t record) {
    string k1 = string(key1);
    string k2 = string(key2);
    recordMap* cluster = &clusters[k2];
    //cout << "pc_rerecord(..): Fetch iterator on key1-Element\n";
    recordMap::iterator oldRecord = cluster->find(k1);
    //cout << "pc_rerecord(..): oldRecord != cluster->end():" <<
    (oldRecord != cluster->end()) << "\n";
    if(oldRecord == cluster->end()) {
    cluster->insert(recordMap::value_type(k1, record));
    } else {
    oldRecord->second = record;
    }
    //cout << "pc_rerecord(..): return\n";
    return SUCCEED;
    }

    ....
    };

    /*************************************************************************/
    /* C implementation of TermCache.h passes calls to cpp TermCache object. */
    /*************************************************************************/

    static TermCache tc;

    // SWI: In: foreign_t Out: record_t
    // BIM: In: 0, 1 Out: C-Datentypen
    int pc_record(char* key1, char* key2, record_t record) {
    return tc.pc_record(key1, key2, record);
    }

    int pc_rerecord(char* key1, char* key2, record_t record) {
    return tc.pc_rerecord(key1, key2, record);
    }

    int pc_recorded(char* key1, char* key2, record_t* record) {
    return tc.pc_recorded(key1, key2, record);
    }

    int pc_is_a_key(char* key1, char* key2) {
    return tc.pc_is_a_key(key1, key2);
    }

    int pc_erase(char* key1, char* key2) {
    return tc.pc_erase(key1, key2);
    }

    int pc_erase_all(char* key2) {
    return tc.pc_erase_all(key2);
    }

    int pc_current_key(char* key1, char* key2, PROLOG_TERM* resultList) {
    return tc.pc_current_key(key1, key2, resultList);
    }


    Logger:

    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <string>
    #include <sstream>
    using namespace std;

    #define TRACE 0
    #define DEBUG 1
    #define INFO 2
    #define WARN 3
    #define FATAL 4

    class Logger {

    string logfile;
    int level;

    public:
    Logger(string file) {
    level = TRACE;
    logfile = getenv("HOME");
    logfile += "/";
    logfile += file;
    // value at this point is logfile == "/home/kensche/TermCache.log"
    }

    void setLevel(int logLevel) {
    level = logLevel;
    }

    void trace(string msg) {
    if(level <= TRACE) {
    std::eek:fstream out;
    out.open(logfile.c_str(), ios_base::eek:ut | ios_base::app);
    out << "TRACE:" << msg << "\n";
    out.close();
    }
    }

    void debug(string msg) {
    if(level <= DEBUG) {
    std::eek:fstream out;
    out.open(logfile.c_str(), ios_base::eek:ut | ios_base::app);
    out << "DEBUG:" << msg << "\n";
    out.close();
    }
    }

    void info(string msg) {
    if(level <= INFO) {
    std::eek:fstream out;
    out.open(logfile.c_str(), ios_base::eek:ut | ios_base::app);
    out << "INFO:" << msg << "\n";
    out.close();
    }
    }

    void warn(string msg) {
    if(level <= WARN) {
    std::eek:fstream out;
    out.open(logfile.c_str(), ios_base::eek:ut | ios_base::app);
    out << "WARN:" << msg << "\n";
    out.close();
    }
    }

    void fatal(string msg) {
    if(level <= FATAL) {
    std::eek:fstream out;
    out.open(logfile.c_str(), ios_base::eek:ut | ios_base::app);
    out << "FATAL:" << msg << "\n";
    out.close();
    }
    }

    private:
    void operator=(const Logger&);
    void operator&();
    void operator,(const Logger&);
    };
     
    David Kensche, Oct 12, 2004
    #6
  7. David Kensche wrote:
    > Thank you for all the hints, but it doesn't work yet.
    > I replaced as much char* by string as I could, but to
    > client modules (from C) this class has to look like C,
    > and this is the reason why I need char* in the interface.
    > The situation even worsened. Now I even do not need to
    > create the Logger to cause a "bus error".
    > My new source code looks like this:
    >
    > [...]


    Whatever the problem is, it's not in the "Logger" any longer.
    The presented source code is incomplete and causes making some
    assumptions that render any advice impossible.

    Debug your program. That's what we all do when we have similar
    problems. Compile it with debugging information in, run it under
    the debugger, see where it breaks. Look at variables, analyse
    the call stack... You know, programming is not just writing code.

    V
     
    Victor Bazarov, Oct 12, 2004
    #7
  8. "David Kensche" <-aachen.de> wrote in message
    news:...
    > Thank you for all the hints, but it doesn't work yet.
    > I replaced as much char* by string as I could, but to
    > client modules (from C) this class has to look like C,
    > and this is the reason why I need char* in the interface.
    > The situation even worsened. Now I even do not need to
    > create the Logger to cause a "bus error".
    > My new source code looks like this:
    >


    Are you sure that the pointers being passed into your code are correct?

    I couldn't see anything wrong in the posted code.

    john
     
    John Harrison, Oct 12, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Don Golding
    Replies:
    2
    Views:
    565
    Leon Heller
    Apr 15, 2004
  2. William
    Replies:
    5
    Views:
    477
    Alf P. Steinbach
    Mar 22, 2005
  3. Giuseppe

    Re: Character assignment causes bus error

    Giuseppe, Jun 24, 2003, in forum: C Programming
    Replies:
    1
    Views:
    1,552
    Giuseppe
    Jun 24, 2003
  4. Atreya, Chaitanya

    A Case of BUS Error !

    Atreya, Chaitanya, Aug 3, 2003, in forum: C Programming
    Replies:
    4
    Views:
    424
    Vivek Mohan
    Aug 3, 2003
  5. ben
    Replies:
    4
    Views:
    657
    Martin Ambuhl
    Jun 26, 2004
Loading...

Share This Page