Segmentation fault when calling fread() c++ - c++

I dont understand the mistake I am making.
I tryed alot but I am unable to read my FILE.
Basically I write an structure into a file named 0.txt / 1.txt / 2.txt ... based of account amound.
I realy seached hours to fix my problem but I dont understand how I can fix and why I get the ERROR.
Also I have no problem in complining my code (with dev c++) but when I press on Load Accounts Button I get the ERROR "Segmentation Fault" (using windows 7).
I noticed that the problem is at fread() line in function ladeAccounts().
The name of my Structure is "iAccount".
The variable infoma is as iAccount typed and the "number of accounts existing" typed as int anzahl in newAccount() decides the path.
iAccount looks like this:
struct iAccount
{
string ID;
string password;
int level;
};
This is how I write my STRUCT into the FILE:
void Account::newAccount(int anzahl, string username, string pw, int lvl)
{
iAccount neu;
neu.ID = username;
neu.password = pw;
neu.level = lvl;
ss.str("");
ss<<anzahl;
s = ss.str();
s = "Accounts/"+s+".txt";
f1 = fopen(s.c_str(), "w");
fseek(f1, 0, SEEK_SET);
fwrite(&infoma, sizeof(iAccount), 1, f1);
fclose(f1);
}
This is how I read the File (ERROR APPEARS when I call fread()
void Account::ladeAccount(int nummer)
{
stringstream sa;
iAccount account_geladen;
sa.str("");
sa<<nummer;
s = sa.str();
s = "Accounts/"+s+".txt";
f2 = fopen(s.c_str(), "r");
fseek(f2, 0, SEEK_SET);
fread(&infoma, sizeof(infoma), 1, f2);
fclose(f2);
}
Thank you for your help. I have no clue where my problem is and as I said I am searching for hours.
EDIT:
The file gets opened I tryed it (f2 is true!).
EDIT":
ERRNO = 0 !!!
SEE HERE:
ostringstream Str;
Str << errno;
infoma.ID = Str.str();
Just did this to see the result of errno in my wxtextlabel.

Reason
You are most probably calling fread on a NULL file handle. So you have two problems here:
In your code (you don't check if fread succeeds or returns a NULL value)
Your file can't be opened for some reason (this, you should investigate...)
Explication
fopen (see documentation) can return a NULL handle for different reasons. If you don't check the validity of the handle before calling fread you will have a segmentation fault.
Tips
As you can read in the official documentation I linked above, on most library implementations the errno variable can help you giving the system-specific error code on failure. This could help you debugging your error in opening the file.
Side Issues
Once you solve this bug in our code you will have other issues. As people (notably #Christophe) remarked in other answers, there is a structural problem in your code because you try to serialize/deserialize on your file objects non POD (aka your strings). Since string are complex objects you can't serialize them directly.
The approach of using an array of characters will work correctly, as simple types can be handled the way you coded.
For this reason, you can use the std::string c_str() method to obtain a null terminated array of chars from your string and store it in the file.
The opposite operation is even more straightforward, as you can initialize a std::string simply passing the deserialized array of chars:
std::string str(the_array);

You have a problem because you use fread() to load binary data. But this works only with plain old data (POD) objects.
It uses to give desastrous results with less trivial objects especially if the internals of these manage dynamic memory allocaton and/or pointers like it's the case here with strings.
By the way:
If you read/write binary data, you should really use "rb"/"wb" as mode for fopen(). If you don't you would'nt necessary have a seg.fault, but your data might be incorrect on some systems.
Edit:
Sorry, I didn't read well enough: if it happens right at fread() the reason provided by Alex will certainly help. However I leave this answer because as soon as you've solved your fopen() issue, you might get segmentation errors if you try to work with the object that you've read. If you're not conviced, look at sizeof(iAccount) and compare it to the size your string content.

EDIT
if(f2) is true so I am wrong and file got opened successfull right?
I found out that the file is not opened/the fopen can not handle with the path for example 0.txt .
Also I tryed to enter the path directly without building it (without stringstream and so on). Still I have the problem of the segmentation fault. I checked everything the file exists in the folder Accounts. I have an other file called "Accounts.txt" in the same folder and there I have no problem reading the amound of accounts existing (also using a struct). There I dont even check if the fopen had success but it works anyway I will write the code for the file-open-check later.
The code for the reading/writing into Accounts/Accounts.txt is:
struct init{
int anzahl_1;};
init anzahl;
FILE* f;
static string ss = "Accounts/Accounts.txt";
int account_anzahl1()
{
f = fopen(ss.c_str(), "r");
fread(&anzahl, sizeof(init), 1, f);
fseek(f, 0, SEEK_END);
fclose(f);
return anzahl.anzahl_1;
}
void account_anzahl_plus()
{
anzahl.anzahl_1 = anzahl.anzahl_1 +1;
f = fopen(ss.c_str(), "w");
fwrite(&anzahl, sizeof(init), 1, f);
fclose(f);
}
There I have no problem!

Related

returning JsonDoc as a reference from a method

I have the following method which gives out a jsonDoc as a reference
bool MyClass::jsonTest(rapidjson::Document & rjsonDoc)
{
rjsonDoc.SetObject();
rapidjson::Value val(rapidjson::kObjectType);
val.AddMember("a", 1, rjsonDoc.GetAllocator());
val.AddMember("b", 2, rjsonDoc.GetAllocator());
val.AddMember("c", 3, rjsonDoc.GetAllocator());
rjsonDoc.AddMember("Values", val, rjsonDoc.GetAllocator());
//outputs the json into a file
std::FILE* fp = fopen("outputjsonTest.json", "wb"); // non-Windows use "w"
char writeBuffer[65536];
rapidjson::FileWriteStream os(fp, writeBuffer, sizeof(writeBuffer));
rapidjson::Writer<rapidjson::FileWriteStream> writer(os);
rjsonDoc.Accept(writer);
fclose(fp);
return false;
}
The above method when called writes a perfect json into the file outputjsonTest.json
But upon calling the method in another class and writing it into the file,
rapidjson::Document d;
CData_BisconaCtrl dMan;
dMan.jsonTest(d);
//outputs the json into a file
std::FILE* fp = fopen("outputruntest.json", "wb"); // non-Windows use "w"
char writeBuffer[65536];
rapidjson::FileWriteStream os(fp, writeBuffer, sizeof(writeBuffer));
rapidjson::Writer<rapidjson::FileWriteStream> writer(os);
d.Accept(writer);
fclose(fp);
The file, outputruntest.json turns out to be blank.
It seems I cannot use the pass by reference style to return a jsonDocument from a method. Or am I making a mistake? Is it possible to return a jsonDocument in this way, at all?
I see nothing wrong with what you are doing. Moreover, I tried running your code and it seemed to work for me.
That said, you should note that if you try to use the Writer more than once (e.g., to print more than one document or to print the same document a second time), you'll need to Reset() it, first. It will stop producing output at the end of the first document, so if you try to print a second one it won't produce any output (because the result would not be a legal JSON "document").
[Edit:]
Nevertheless, rather than dumping the object to a file, you could try interrogating it to see what's in it. Check its type, size, capacity; see if it has the expected members, or iterate over its members/entries; etc. Failing all that, I would try proving that the basic C++ stuff is working. (I.e.: Is the right method actually being called? Are there any unexpected exceptions which are being handled? Is the method receiving the object that you're sending? Etc.)
Good luck!

Trash characters when using buffers in c++

I have a DLL that I need to handle in C++. I'm using WxWidgets (standard compilation, but I also tried Unicode on/off) and NetBeans. I also tried dealing with this without WxWidgets (windows.h) and had same problems.
Here is how I access the DLL functions using WxWidgets:
// -------------------- POINTERS TO FUNCTIONS
typedef bool(*TYPE_DLL_SetLicense)(char*, char*);
typedef bool(*TYPE_DLL_PingConnection)(char*);
typedef char*(*TYPE_DLL_ERR_DESCRIPTION)(void);
class DLL_Library
{
public:
// pointers to functions inside dll
TYPE_DLL_SetLicense DLL_SetLicense; //initialize - will wor fine as it returns only true/false (buffer only provide data)
TYPE_DLL_PingConnection DLL_PingConnection; //ping to serwer. Will return trahs, becouse it uses buffer to provide data ang get answear back
TYPE_DLL_ERR_DESCRIPTION DLL_ERR_DESCRIPTION; //error description. No buffer, no trouble. Returns correct string.
wxDynamicLibrary dynLib2;
int initialize(void)
{
//patch to dll
wxString path = wxStandardPaths::Get().GetExecutablePath().BeforeLast('\\') + _("\\DLL_dll\\DLLMOK.dll");
if(!wxFile::Exists(path)) return -1;
//load dll
if(!dynLib2.Load(path)) return -2;
//Assign functions in dll to variable
DLL_SetLicense=(TYPE_DLL_SetLicense) dynLib2.GetSymbol(wxT("DLL_SetLicense"));
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
DLL_ERR_DESCRIPTION=(TYPE_DLL_ERR_DESCRIPTION) dynLib2.GetSymbol(wxT("DLL_ERROR_DESCRIPTION"));
return 0;
}
};
And here is the function I run. It should return and XML content, that I try to save to the file.
//DLL_PingConnection
//result ping to be save in file
wxFile file_ping_xml;
plik_ping_xml.Open(wxT("C:\\dll\\ping.xml"),wxFile::write);
char buffor_ping_xml[2000];
//I run the function here
bool is_ping = DLL_PingConnection(buffor_ping_xml);
if(is_ping)
{
tex_box->AppendText(wxT("DLL_PingConnection True\n"));
//we save result to file
bool is_write_ping_ok = file_ping_xml.Write(buffor_ping_xml,2000);
if (is_write_ping_ok){tex_box->AppendText(wxT("Save to file is ok ok\n"));}
else {tex_box->AppendText(wxT("Save to file failed :( \n"));}
}
else
{
tex_box->AppendText(wxT("DLL_PingConnection False\n"));
}
std::cout << "Error description: " << DLL_ERR_DESCRIPTION() << "\n"; //will work fine both in saving to file, and in streaming to screen.
The problem is that inside the file instead of good content I get rubbish like this:
NOTE that this only happens in functions that use buffers like:
char buffer[2000] //buffer will contain for example file xml
function do_sth_with_xml(buffer) //buffer containing xml will (should) be overwriten with xml results of the function - in our case DLL_PingCONNECTION should save in buffer xml with connection data
Documentation say that the DLL operates on Windows-1250. File ping.xml I have set to windows ANSI, but I don't think problem lies here.
EDIT: I have written problem without WxWidgets (I load DLL using windows.h) - same problems. Here is the code: Getting trash data in char* while using it as buffer in function . Please help :(
This
DLL_PingConnection=(TYPE_DLL_PingConnection)
shouldn't it be
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
?
seems otherwise you will not get a valid pointer to the function in the DLL.
as a general rule you should check return values, especially from a DLL
you load dynamically since it happens that you sometimes get another version
of the DLL which may have a function with same name but other signature or
where is missing entirely.
You named a function
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(....
and call it with
OSOZ.OSOZ_PingConnection(buffor_ping_xml);
you typedef a function
typedef bool(*TYPE_DLL_PingConnection)(char*);
you create a variable
char buffor_ping_xml[2000];
in your typedef it is char* and your buffor_ping_xml is char
how can that work ?
try
char *buffor_ping_xml = new char[2000];
/* or */
wchar_t *buffor_ping_xml = new wchar_t[2000];
/* or */
wxChar *buffor_ping_xml = new wxchar[2000];
bool is_ping = DLL_PingConnection(buffor_ping_xml);
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
write mystring to file.
To Do:
look in your wxwidgets\libs folder for your libs
are there libwxmsw29ud_* with a 'u' in the name (after version number here 29)?
If not You can not use unicode
If yes next steps
for all different test char *, wchar_t *, wxChar * give the files different name.
for example file_ping_xml.Open(wxT("C:\dll\ping_w_t_FromUTF8.xml"), ...
for wchar_t * in combination with
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
also in combination with
wxString mystring(buffor_ping_xml);
Then check out the look like, of the files in a browser .
To test you can go to your wxWidgets sample folder . Compile in the folder C:\wxWidgets\samples\docview\docview.cpp . Open with docview.exe a unicode file . How does it look.
Unicode download file
Unicode-related compilation settings
You should define wxUSE_UNICODE to 1 to compile your program in Unicode mode. This currently works for wxMSW, wxGTK, wxMac and wxX11. If you compile your program in ANSI mode you can still define wxUSE_WCHAR_T to get some limited support for wchar_t type.
Here is answear: Getting trash data in char* while using it as buffer in function.
Thanks everyone - expecially for patience.

How can writing memory to a filebuffer mutate it?

For a while now, I have been experiencing an extremely odd problem when trying to write memory to a filebuffer in C++. The problem only occurs on MinGW. When I compile under gcc/linux, everything is fine.
Debugging Session displaying the problem
So basically, I'm writing code from a memory buffer to a filebuffer, and the binary representation in the file ends up being different from the memory I wrote. No, the file is not being modified at a later point, I ensured this by using the debugger to exit the program after closing the file. I have no idea how something like this is even possible, I even used valgrind to see if there were any memory allocation problems, but nope.
I'll paste some of the related code.
/// a struct holding information about a data file
class ResourceFile {
public:
string name;
uint32 size;
char* data;
ResourceFile(string name, uint32 size);
};
ResourceFile::ResourceFile(string name, uint32 size)
: name(name), size(size)
{
// will be free'd in ResourceBuilder's destruction
data = (char*) malloc(size * sizeof(char));
}
/// Build a data resource from a set of files
class ResourceBuilder {
public:
ofstream out; ///< File to put the resource into
vector<ResourceFile> input; ///< List of input strings
/// Add a file from disk to the resource
void add_file(string filename);
/// Create a file that the resource will be written to
void create_file(string filename);
~ResourceBuilder();
};
void ResourceBuilder::create_file(string filename) {
// open the specified file for output
out.open(filename.c_str());
uint16 number_files = htons(input.size());
out.write((char*) &number_files, sizeof(uint16));
foreach(vector<ResourceFile>,input,i) {
ResourceFile& df = *i;
uint16 name_size = i->name.size();
uint16 name_size_network = htons(name_size);
out.write((char*) &name_size_network, sizeof(uint16));
out.write(i->name.c_str(),name_size);
uint32 size_network = htonl(i->size);
out.write((char*) &size_network, sizeof(i->size) );
out.write(i->data, i->size);
}
out.close();
/// \todo write the CRC
}
The following is how the memory is allocated in the first place. This is a possible source of error, because I copypasted it from somewhere else without bothering to understand it in detail, but I honestly don't know how the method in which I allocated memory could be a reason for filebuffer output being different from the memory that I'm writing.
void ResourceBuilder::add_file(string filename) {
// loads a file and copies its content into memory
// this is done by the ResourceFile class and there is a
// small problem with this, namely that the memory is
// allocated in the ResourceFile directly,
ifstream file;
file.open(filename.c_str());
filebuf* pbuf=file.rdbuf();
int size=pbuf->pubseekoff (0,ios::end,ios::in);
pbuf->pubseekpos (0,ios::in);
ResourceFile df(filename,size);
pbuf->sgetn (df.data,size);
file.close();
input.push_back(df);
}
I'm really out of ideas. It's also not a bug pertaining to my compiler setup, as other people compiling the code under MinGW get the same error. The only explanation I can think of at this point is a bug with MinGW's filebuffer library itself, but I honestly have no idea.
You need to open the file in binary mode. When you open it in text mode on Windows, line feeds (0x0A) will get converted to CR/LF pairs (0x0D, 0x0A). On Linux you don't see this because Linux uses a single LF (0x0A) as the line terminator in text files, so no conversion is done.
Pass the ios::binary flag to the ostream::open method:
out.open(filename.c_str(), ios::out | ios::binary);
You should also use this flag when reading binary files, so that the opposite conversion isn't performed:
ifstream file;
file.open(filename.c_str(), ios::in | ios::binary);
The problem is that you open your file in text mode! In that case, 0x0a (Linefeed) is converted to 0x0d0a (Carriage return line feed). This is why you see a difference in the file and memory.
use out.open(filename.c_str(), ios::binary | ios::out);

How do I get a string or stream into a CStreamFile?

this question may seem a bit too specific, but I figure I'd give it a shot here since I've found some great programming answers here in the past.
I am modifying the open-source program TinyCad for a project I'm working on. I've visited the TinyCad message board and posted, but I didn't get the answer I'm looking for. I'm having trouble wrapping my head about how to integrate a small XML converter class I wrote into the loading function of TinyCad.
A little background about me: I have no experience with MFC or Visual Studio, but that is what I have to use. I am used to C++ and was taught using iostream syntax (cout, cin, new, etc.) so I'm not used to older C code (like printf, sprintf, malloc, alloc, etc.) either. I usually write my programs from start to finish in Qt, but I was told that for this project I should modify an existing program to save time. I don't know if it'll save that much time if I have to learn something totally foreign, but I digress.
I wrote a small class to read in an XML file that is structured differently than the XML file that TinyCad reads in. My class converts it and outputs an intermediate XML file. Well, I don't want to spit out an intermediate file. I modified it to save the output as a string (using the string datatype from the standard C++ iostream library). I want to get this string into a stream so that TinyCad can open the file, do the conversion, and then continue loading.
My class is called like so:
std::string blah;
char* filename = "library.xml";
XMLopen myXML(filename, blah);
So it takes in a filename, opens the file, parses the relevant information out of the file, puts the information into TinyCad's XML structure, and saves the XML code as a string that has been passed by reference.
I had an idea to use istringstream to make a stream, but that did not play nice with CFile. I tried it like so:
istringstream ins; // Declare an input string stream.
ins.str(blah);
// First open the stream to save to
CFile theFile(ins);
Below is the code in TinyCad that opens and loads the selected XML file:
void CLibraryStore::LoadXML( const TCHAR *filename )
{
// First open the stream to save to
CFile theFile;
// Open the file for saving as a CFile for a CArchive
BOOL r = theFile.Open(filename, CFile::modeRead);
if (r)
{
CString name;
// Create the XML stream writer
CStreamFile stream( &theFile, CArchive::load );
CXMLReader xml( &stream );
// Get the library tag
xml.nextTag( name );
if (name != "Library")
{
Message(IDS_ABORTVERSION,MB_ICONEXCLAMATION);
return;
}
xml.intoTag();
CTinyCadApp::SetLockOutSymbolRedraw( true );
while ( xml.nextTag( name ) )
{
// Is this a symbol?
if (name == "SYMBOL")
{
// Load in the details
xml.intoTag();
CTinyCadMultiSymbolDoc temp_doc;
drawingCollection drawing;
CLibraryStoreNameSet s;
// this is where the stream gets sent to be loaded into the data structure
s.LoadXML( &temp_doc, xml );
xml.outofTag();
// ... and store the symbol
Store( &s, temp_doc );
}
}
xml.outofTag();
CTinyCadApp::SetLockOutSymbolRedraw( false );
}
}
Edit 7/28/2010 5:55PM
So I tried to make a stream, but it fails.
CStreamFile takes in a filename and then gets set as a CArchive:
m_pArchive = new CArchive( theFile, nmode );
I tried to make a CStream like so (since CStreamFile is an overloaded CStream):
CString test = blah.c_str();
CStreamMemory streamCS;
streamCS << test;
CXMLReader xml( &streamCS );
But at streamCS << test; it doesn't put the stream in at all. test gets assigned correctly with blah so I know that's working.
Any ideas on how to approach this?

How to set binary data using setBlob() in C++ connector

I know this has been asked before, and I tried to implement the solution, but I just get exception errors when I call ps->executeUpdate(). Has anyone got an explicit example?
This post is a bit old, but I ran across the same question. I employed the method above and it didn't quite work right for my case, which was trying to take a vector and use that for the stream. What I was doing was taking a UUID and converting it into a 16 byte binary version to use in the table. Using the method above, I found that only half my buffer was being populated.
I ended up using a stringstream.
std::vector<unsigned char> convertedId;
std::stringstream stream;
// convertedId has been populated with the 16 byte binary version
stream = std::stringstream(std::string(convertedId.begin(), convertedId.end()));
// Parameter 1 is BINARY(16)
pStatement->setBlob(1, &stream);
A few other things to keep in mind. The stream is not accessed until one of the execute variants is called. So you'll need to keep the stream around until you have run execute.
Hopefully this will help someone and save them time.
Sorry Matthew - I assumed the previous answer to this question (by elrohin). Maybe I should have replied to that. Anyway heres the code he suggested:
class DataBuf : public streambuf
{
public:
DataBuf(char * d, size_t s) {
setg(d, d, d + s);
}
};
// prepare sql update statement etc. and set the data pointer
string* pData = ; // ...not part of the original answer
DataBuf buffer((char*)pData->data(), pData->length());
istream stream(&buffer);
ps->setBlob(1, &stream);
ps->executeUpdate(); // This causes an exception in free.c
I'm using VS9 with the latest (beta) connector/cpp debug libs. I've also tried using char* instead of string.
This code works fine for me:
Driver *driver;
Connection *conn;
driver = get_driver_instance();
conn = driver->connect("tcp://127.0.0.1:3306", "root", "root");
std::auto_ptr use_stmt(conn->createStatement());
use_stmt->execute("USE world");
std::auto_ptr stmt(conn->prepareStatement("INSERT INTO terrain_texture_tiles_0 (data) VALUES(?)"));
std::string value("A\0B", sizeof("A\0B") - 1);
std::istringstream tmp_blob(value);
stmt->setBlob(1, &tmp_blob);
stmt->execute();
hope it helps ... Jaroslav Pribyl