Newbie: bus error

D

David Kensche

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&);
};
 
J

John Harrison

David Kensche said:
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
 
J

John Harrison

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
 
V

Victor Bazarov

David said:
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
 
P

Peter van Merkerk

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().
 
D

David Kensche

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&);
};
 
V

Victor Bazarov

David said:
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
 
J

John Harrison

David Kensche said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top