"Unable to read memory" When using "FILE* file" (C++) on WindowPhone8 - c++

i got problem when using "FILE* file;" with C++ on WP8.
My app crash when meet the line above.
When i debug, i saw:
1. All the member of this variable "file" got message:
(file)->_ptr: Unable to read memory.
(file)->_cnt: Unable to read memory.
(file)->_base: Unable to read memory.
(file)->_flag: Unable to read memory.
(file)->_file: Unable to read memory.
(file)->_charbuf: Unable to read memory.
(file)->_tmpfname: Unable to read memory.
(file)->_bufsiz: Unable to read memory.
I have no idea to fix it.
And this is the code i Use:
void SubMenu::LoadConfig(float dt)
{
TiXmlDocument doc;
bool flag = doc.LoadFile("Config\Config.xml");// Error here.
TiXmlElement* root = doc.FirstChildElement();
for (TiXmlElement* elem = root->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement())
{
std::string elemName = elem->Value();
int Star = atoi(elem->GetText());
if (elemName == "Tractor")
{
this->AddStarPoint(Level1, 4, Star);
}
if (elemName == "EggsCatch")
{
this->AddStarPoint(Level2, 3, Star);
}
if (elemName == "EggsCatch2")
{
this->AddStarPoint(Level3, 4, Star);
}
}
}
This is tinyxml.cpp got function LoadFile:
bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
{
TIXML_STRING filename( _filename );
value = filename;
// reading in binary mode so that tinyxml can normalize the EOL
FILE* file = TiXmlFOpen( value.c_str (), "rb" ); // Error here.
if ( file )
{
bool result = LoadFile( file, encoding );
fclose( file );
return result;
}
else
{
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
}
Please help!
Thanks!

I suppose file == NULL because of a single backslash \ in the path. Try
(simpler) replacing it with a slash "Config/Config.xml", or
(better) escape it with another backslash "Config\\Config.xml".

Related

c++ win32 environment, taglib error

I want to extract albumart from mp3 files
so i use taglib library
extracting title and artist succed.
but when i try to extract album art, it occurs error.
void MusicContainer::getAlbumArt(const char* path) {
static const char *IdPicture = "APIC";
TagLib::MPEG::File mpegFile(path);
TagLib::ID3v2::Tag *id3v2tag = mpegFile.ID3v2Tag();
TagLib::ID3v2::FrameList Frame;
TagLib::ID3v2::AttachedPictureFrame *PicFrame;
void *RetImage = NULL, *SrcImage;
unsigned long Size;
FILE *jpegFile;
errno_t err = fopen_s(&jpegFile, "d:\\FromId3.jpg", "wb");
if (id3v2tag)
{
// picture frame
Frame = id3v2tag->frameListMap()[IdPicture];//error occurs on this line.
if (!Frame.isEmpty())
{
for (TagLib::ID3v2::FrameList::ConstIterator it = Frame.begin(); it != Frame.end(); ++it)
{
PicFrame = (TagLib::ID3v2::AttachedPictureFrame *)(*it);
//  if ( PicFrame->type() ==
//TagLib::ID3v2::AttachedPictureFrame::FrontCover)
{
// extract image (in it’s compressed form)
Size = PicFrame->picture().size();
SrcImage = malloc(Size);
if (SrcImage)
{
memcpy(SrcImage, PicFrame->picture().data(), Size);
fwrite(SrcImage, Size, 1, jpegFile);
fclose(jpegFile);
free(SrcImage);
}
}
}
}
}
else
{
cout << "id3v2 not present";
}
}
error message
Exception thrown: write access violation.
_Parent_proxy was 0x10011EE0.
If there is a handler for this exception, the program may be safely continued.
tell me how to fix it.

`fgetpos` Not Returning the Correct Position

Update: To get around the problem below, I have done
if (ftell(m_pFile) != m_strLine.size())
fseek(m_pFile, m_strLine.size(), SEEK_SET);
fpos_t position;
fgetpos(m_pFile, &position);
this then returns the correct position for my file. However, I would still like to understand why this is occurring?
I want to get the position in a text file. For most files I have been reading the first line, storing the position, doing some other stuff and returning to the position afterwards...
m_pFile = Utils::OpenFile(m_strBaseDir + "\\" + Source + "\\" + m_strFile, "r");
m_strLine = Utils::ReadLine(m_pFile);
bEOF = feof(m_pFile) != 0;
if (bEOF)
{
Utils::CompilerError(m_ErrorCallback,
(boost::format("File '%1%' is empty.") % m_strFile).str());
return false;
}
// Open.
pFileCode = Utils::OpenFile(strGenCode + "\\" + m_strFile, options.c_str());
m_strLine = Utils::Trim(m_strLine);
Utils::WriteLine(pFileCode, m_strLine);
// Store location and start passes.
unsigned int nLineCount = 1;
fpos_t position;
fgetpos(m_pFile, &position);
m_strLine = Utils::ReadLine(m_pFile);
...
fsetpos(m_pFile, &position);
m_strLine = Utils::ReadLine(m_pFile);
With all files provided to me the storage of the fgetpos and fsetpos works correctly. The problem is with a file that I have created which looks like
which is almost identical to the supplied files. The problem is that for the file above fgetpos(m_pFile, &position); is not returning the correct position (I am aware that the fpos_t position is implementation specific). After the first ReadLine I get a position of 58 (edited from 60) so that when I attempt to read the second line with
fsetpos(m_pFile, &position);
m_strLine = Utils::ReadLine(m_pFile);
I get
on 700
instead of
Selection: Function ADJEXCL
Why is fgetpos not returning the position of the end of the first line?
_Note. The Utils.ReadLine method is:
std::string Utils::ReadLine(FILE* file)
{
if (file == NULL)
return NULL;
char buffer[MAX_READLINE];
if (fgets(buffer, MAX_READLINE, file) != NULL)
{
if (buffer != NULL)
{
std::string str(buffer);
Utils::TrimNewLineChar(str);
return str;
}
}
std::string str(buffer);
str.clear();
return str;
}
with
void Utils::TrimNewLineChar(std::string& s)
{
if (!s.empty() && s[s.length() - 1] == '\n')
s.erase(s.length() - 1);
}
Edit. Following the debugging suggestions in the comments I have added the following code
m_pFile = Utils::OpenFile(m_strBaseDir + "\\" + Source + "\\" + m_strFile, "r");
m_strLine = Utils::ReadLine(m_pFile);
// Here m-strLine = " Logic Definition Report Chart Version: New Version 700" (64 chars).
long vv = ftell(m_pFile); // Here vv = 58!?
fpos_t pos;
vv = ftell(m_pFile);
fgetpos(m_pFile, &pos); // pos = 58.
fsetpos(m_pFile, &pos);
m_strLine = Utils::ReadLine(m_pFile);
Sorry, but your Utils functions have clearly been written by an incompetent. Some issues are just a matter of style. For trimming:
void Utils::TrimNewLineChar(std::string& s)
{
if (!s.empty() && *s.rbegin() == '\n')
s.resize(s.size() - 1); // resize, not erase
}
or in C++11
void Utils::TrimNewLineChar(std::string& s)
{
if (!s.empty() && s.back() == '\n')
s.pop_back();
}
ReadLine is even worse, replace it with:
std::string Utils::ReadLine(FILE* file)
{
std::string str;
char buffer[MAX_READLINE];
if (file != NULL && fgets(buffer, MAX_READLINE, file) != NULL)
{
// it is guaranteed that buffer != NULL, since it is an automatic array
str.assign(buffer);
Utils::TrimNewLineChar(str);
}
// copying buffer into str is useless here
return str;
}
That last str(buffer) in the original worries me especially. If fgets reaches a newline, fills the buffer, or reaches end of file, you're guaranteed to get a properly terminated string in your buffer. If some other I/O error occurs? Who knows? It might be undefined behavior.
Best not to rely on the value of buffer when fgets fails.

Loading Local Content in Awesomium

I have written a local DataSource because from what I know there are none included in Awesomium, but the thing is that it request everything from the data source html, images etc
And I have no clue on how I should load all types of mime formats.
My current code only supports html/text, where I load the file into binary and send as a response. This does not work for images.
Does anybody know where I should go on from here?
class LocalDataSource :
public Awesomium::DataSource
{
public:
LocalDataSource() { }
virtual ~LocalDataSource() { }
virtual void OnRequest(int request_id, const Awesomium::WebString& path)
{
std::string filepath = Awesomium::ToString(path).insert(0, "./");
std::basic_ifstream<char> is(filepath, std::ios_base::in | std::ios_base::binary);
if (is)
{
is.seekg(0, is.end);
int length = is.tellg();
is.seekg(0, is.beg);
char *buffer = new char[length + 1];
is.read(buffer, length);
buffer[length] = '\0';
is.close();
SendResponse(request_id, strlen(buffer), (unsigned char*)buffer, Awesomium::WSLit("text/html"));
delete[] buffer;
}
else
{
// Error
}
}
};
EDIT:
for now I will load the file relative to the executable and not use DataSource's.
I know this is old, but it was relevant to me, I fixed this the same way as Steven did, I will post the C++ code I used:
bool ResInterceptor::OnFilterNavigation(int origin_process, int origin_routing_id, const Awesomium::WebString& method, const Awesomium::WebURL& url, bool is_main_frame)
{
return false;
}
Awesomium::ResourceResponse* ResInterceptor::OnRequest(Awesomium::ResourceRequest* request)
{
bool isAsset = std::strcmp(ToString(request->url().scheme()).c_str(), "asset")==0;
bool isFile = std::strcmp(ToString(request->url().scheme()).c_str(), "file")==0;
if(!isAsset && !isFile)
{
//if it is neither of these we "may" still intercept the call, this allows for offline-online versions to work
return Awesomium::ResourceInterceptor::OnRequest(request);
}
if(isAsset)
{
//Blah blah, do whatever
}
else if(isFile)
{
//Blah blah, same
}
//As you can see this isn't very, but it worked for my purposes
std::string contentpath = "E:/Location/of/files" + ToString(request->url().path());
Awesomium::WebString datatype;
std::string filename = Awesomium::ToString(request->url().filename());
//I still want to check for the correct mime type
if (has_suffix(filename, ".html")) datatype = Awesomium::WSLit("text/html");
else if(has_suffix(filename, ".js")) datatype = Awesomium::WSLit("text/javascript");
else if(has_suffix(filename, ".css")) datatype = Awesomium::WSLit("text/css");
else if(has_suffix(filename, ".swf")) datatype = Awesomium::WSLit("application/x-shockwave-flash");
else if(has_suffix(filename, ".zip")) datatype = Awesomium::WSLit("application/zip");
else if(has_suffix(filename, ".txt")) datatype = Awesomium::WSLit("text/plain");
else if(has_suffix(filename, ".text")) datatype = Awesomium::WSLit("text/plain");
else if(has_suffix(filename, ".png")) datatype = Awesomium::WSLit("image/png");
else if(has_suffix(filename, ".jpeg")) datatype = Awesomium::WSLit("image/jpeg");
else if(has_suffix(filename, ".jpg")) datatype = Awesomium::WSLit("image/jpeg");
else if(has_suffix(filename, ".webm")) datatype = Awesomium::WSLit("video/webm");
else if(has_suffix(filename, ".mp4")) datatype = Awesomium::WSLit("video/mp4");
else if(has_suffix(filename, ".ogv")) datatype = Awesomium::WSLit("video/ogg");
else if(has_suffix(filename, ".flv")) datatype = Awesomium::WSLit("video/flv");
if(!datatype.IsEmpty())
{
FILE * pFile;
long lSize;
unsigned char * buffer;
size_t result;
pFile = fopen ( contentpath.c_str() , "rb" );
if (pFile!=NULL)
{
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
buffer = (unsigned char*) malloc (sizeof(unsigned char)*lSize);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
// copy the file into the buffer:
result = fread (buffer,1,lSize,pFile);
if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
//This is where the magic happens!!
return Awesomium::ResourceResponse::Create(lSize, buffer, datatype);
// terminate
fclose (pFile);
free (buffer);
}
else
{
//send this off to the default request handler instead of it being a local file
return Awesomium::ResourceInterceptor::OnRequest(request);
}
}else
{
//send this off to the default request handler instead of it being a local file
return Awesomium::ResourceInterceptor::OnRequest(request);
}
}
//Support function
bool ResInterceptor::has_suffix(const std::string &str, const std::string &suffix)
{
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
as for how I hooked it up, I simply added this line of code:
_web_core = WebCore::Initialize(config);
_web_core->set_resource_interceptor(new ResInterceptor());
This took me a whole night to nail down all because I was passing in a pointer with a variable and not using the "new" keyword directly! I got it now at least!
also note, I tried the exact same code above inside the LocalDataSource and it didn't work for anything except the text files, so I think there is a bug in there, good news is, this works the exact same way, but you get more control over every file request.
Thank you Steven for all the great reference code!
The easy way is to send the contents of a file without sweating mime type detection is to use the static method static ResourceResponse* Awesomium::ResourceResponse::Create.
From the Awesomium docs:
Create a ResourceResponse from a file on disk.
I couldn't figure out a way to map ResourceResponse::Create to DataSource::SendResponse.
As a workaround, you could rewrite your data source as an IResourceInterceptor instead of a DataSource. I wrote up a detailed example in C# on how to use http:// scheme instead of the custom asset:// scheme for embedded resources It should be pretty straightforward to translate the C# to C++. Below is an edited down version of my post (not tested).
using System;
using System.IO;
using System.Reflection;
using Awesomium.Core;
namespace MyApp
{
public class ResourceInterceptor : IResourceInterceptor
{
/// <summary>
/// Intercepts any requests for the EmbeddedResourceDomain base Uri,
/// and returns a response using the embedded resource in this app's assembly/DLL file
/// </summary>
public virtual ResourceResponse OnRequest(ResourceRequest request)
{
ResourceResponse response = null;
string resourceName;
string filePath;
filePath = String.Concat("./", request.Url.AbsolutePath);
filePath = Path.GetFullPath(resourceName.Replace('/', Path.DirectorySeparatorChar));
// cache the resource to a temp file if
if (File.Exists(filePath))
{
response = ResourceResponse.Create(filePath);
}
return response;
}
/// <summary>
/// Optionally blocks any web browser requests by returning true. Not used.
/// </summary>
/// <remarks>
/// This method can implement a whitelist of allowed URLs here by
/// returning true to block any whitelist misses
/// </remarks>
public virtual bool OnFilterNavigation(NavigationRequest request)
{
return false;
}
}
}
Another option might be to hack the HTML content to inject a <base href="file:///c:/my/bin/path" /> element inside the <head> of the document. You would need to modify the href attribute value before loading the content. This may be more work than it is worth.

Partial line from cpp file ending up in output file - haunted code?

I'm sorry, it would be extremely difficult to make a fully reproducible version of the error --- so please bare with my schematic code.
This program retrieves information from a web page, processes it, and saves output to an ASCII file. I also have a 'log' file (FILE *theLog---contained within a Manager object) for reporting errors, etc.
Some background methods:
// Prints string to log file
void Manager::logEntry(const string lstr) {
if( theLog != NULL ) { fprintf(theLog, "%s", lstr.c_str()); }
}
// Checks if file with given name already exists
bool fileExists(const string fname) {
FILE *temp;
if( temp = fopen(fname.c_str(), "r") ) {
fclose(temp);
return true;
} else { return false; }
}
// Initialize file for writing (some components omitted)...
bool initFile(FILE *&oFile, const string fname) {
if(oFile = fopen(fname.c_str(), "w") ) { return true; }
else { return false; }
}
The stuff causing trouble:
// Gets data from URL, saves to file 'dataFileName', input control flag 'foreCon'
// stu is some object that has string which i want
bool saveData(Manager *man, Stuff *stu, string dataFileName, const int foreCon) {
char logStr[CHARLIMIT_LARGE]; // CHARLIMIT_LARGE = 2048
sprintf(logStr, "Saving Data...\n");
man->logEntry( string(logStr) ); // This appears fine in 'theLog' correctly
string data = stu->getDataPrefixStr() + getDataFromURL() + "\n"; // fills 'data' with stuff
data += stu->getDataSuffixStr();
if( fileExists(dataFileName) ) {
sprintf(logStr, "save file '%s' already exists.", dataFileName.c_str() );
man->logEntry( string(logStr) );
if( foreCon == -1 ) {
sprintf(logStr, "foreCon = %d, ... exiting.", foreCon); // LINE 'A' : THIS LINE ENDS UP IN OUTPUT FILE
tCase->logEntry( string(logStr) );
return false;
} else {
sprintf(logStr, "foreCon = %d, overwriting file.", foreCon); // LINE 'B' : THIS LINE ENDS UP IN LOG FILE
tCase->logEntry( string(logStr) );
}
}
// Initialize output file
FILE *outFile;
if( !initFile(outFile, dataFileName) ) {
sprintf(logStr, "couldn't initFile '%s'", dataFileName.c_str());
tCase->logEntry( string(logStr) );
return false;
}
fprintf(outFile, "%s", data.c_str()); // print data to output file
if( fclose(outFile) != EOF) {
sprintf(logStr, "saved to '%s'", dataFileName.c_str());
tCase->logEntry( string(logStr) );
return true;
}
return false;
}
If the file already exists, AND 'int foreCon = -1' then the code should print out line 'A' to the logFile. If the file exists and foreCon != -1, the old file is overwritten with data. If the file doesn't exist, it is created, and the data is written to it.
The result however, is that a broken up version of line 'A' appears in the data file AND line 'B' is printed in the log file!!!!
What the data file looks like:
.. exiting.20130127 161456
20130127 000000,55,17,11,0.00
20130127 010000,54,17,11,0.00
... ...
The second line and onward look correct, but there is an extra line that contains part of line 'A'.
Now, the REALLY WEIRD PART. If I comment out everything in the if( foreCon == -1) { ... } block, then the data file looks like:
%d, ... exiting.20130127 161456
20130127 000000,55,17,11,0.00
20130127 010000,54,17,11,0.00
... ...
There is still an extra line, but it is the LITERAL CODE copied into the data file.
I think there is a poltergeist in my code. I don't understand how any of this could happen.
Edit: I've tried printing to console the data string, and it gives the same messed up values: i.e. %d, ... exiting.20130127 161456 - so it must be something about the string instead of the FILE *
Answer based on your latest comment:
getDataPrefixStr() ends up returning a string which starts with
something like string retStr = COMCHAR + " file created on ..."; such
that const char COMCHAR = '#';. Could the COMCHAR be the problem??
You can't add characters and string literals (which are arrays of char, not strings) like that.
You're adding 35 (the ASCII for "#") to the address of " file created on ... ", i.e. getDataPrefixStr() is whatever starts 35 characters from the start of that string. Since all literal strings are stored together in the same data area, you'll get strings from the program in the output.
Instead, you cold do
const string COMCHAR = "*";
string retStr = COMCHAR + " file created on ...";
It could be that logStr is too short and that it is causing data to be overwritten in other buffers (did you double check CHARLIMIT_LARGE?). You can diagnose this by commenting all writes to logStr (sprintf) and see if data is still corrupted. In general, your code is vulnerable to this if a user can set dataFileName (to be a very long string); use snprintf or ostringstream instead.
Otherwise, I would guess that either stu->getDataPrefixStr() or getDataFromURL() are returning corrupted results or return type char* instead of string. Try printing these values to the console directly to see if they are corrupted or not. If they return a char*, then data = stu->getDataPrefixStr() + getDataFromURL() will have undefined behavior.
if( temp = fopen(fname.c_str(), 'r') ) {
should be
if( temp = fopen(fname.c_str(), "r") ) {

SHFileOperation/SHFILEOPSTRUCT

Im trying to copy a directory to a new location. So I am using SHFileOperation/SHFILEOPSTRUCT as follows:
SHFILEOPSTRUCT sf;
memset(&sf,0,sizeof(sf));
sf.hwnd = 0;
sf.wFunc = FO_COPY;
dirName += "\\*.*";
sf.pFrom = dirName.c_str();
string copyDir = homeDir + "\\CopyDir";
sf.pTo = copyDir.c_str();
sf.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI;
int n = SHFileOperation(&sf);
if(n != 0)
{
int x = 0;
}
So I set the values as above. There is a file I created in the folder (I have closed the Handle so it should be fine to move). The SHFileOperation call is returning 2, but I cant find anywhere where these error codes are explained. Does anyone know where I can find out what 2 means, or does anyone have any ideas why it might not be working? Cheers
Error code 2 means The system cannot find the file specified.
See Windows System Error Codes for full listing of error descriptions, or write a function that will obtain the description for the error code:
std::string error_to_string(const DWORD a_error_code)
{
// Get the last windows error message.
char msg_buf[1025] = { 0 };
// Get the error message for our os code.
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
0,
a_error_code,
0,
msg_buf,
sizeof(msg_buf) - 1,
0))
{
// Remove trailing newline character.
char* nl_ptr = 0;
if (0 != (nl_ptr = strchr(msg_buf, '\n')))
{
*nl_ptr = '\0';
}
if (0 != (nl_ptr = strchr(msg_buf, '\r')))
{
*nl_ptr = '\0';
}
return std::string(msg_buf);
}
return std::string("Failed to get error message");
}
From reading the documentation for SHFileOperation the strings specified for pTo and pFrom must be double null terminated: yours are only singly null terminated. Try the following:
dirName.append(1, '\0');
sf.pFrom = dirName.c_str();
string copyDir = homeDir + "\\CopyDir";
copyDir.append(1, '\0');
sf.pTo = copyDir.c_str();