I am using Totalview to debug some code, and it is stopping with a Bus Error.
What is this, and how do I fix it? here is the code snip
In my main:
char *infilename = "/home/dcole/Images/lena1024s.jpg";
/* Try opening a jpeg*/
if( read_jpeg_file( infilename ) > 0 )
{
//do some stuff
}
The function:
int read_jpeg_file( const char *filename )
{
/* these are standard libjpeg structures for reading(decompression) */
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
/* libjpeg data structure for storing one row, that is, scanline of an image */
JSAMPROW row_pointer[1];
FILE *infile = fopen( filename, "rb" ); //this line is where the debugger stops with a Bus Error
unsigned long location = 0;
int i = 0;
if ( !infile )
{
printf("Error opening jpeg file %s\n!", filename );
return -1;
}
return 1;
}
The file I am passing in does exist. I can see that it shows up as the right sting to the full path in the debugger.
I think you're having a memory access problem because of the filename variable...
Instead of:
char *infilename = "/home/dcole/Images/lena1024s.jpg";
try using:
char infilename[] = "/home/dcole/Images/lena1024s.jpg";
Related
I am writing a XOR encryption program which works fine during encryption but during decryption
the
char ca2=fgetc(f);
gets stuck at one point and no decryption takes place after that my best guess about the problem is (the encrypted file contains all sorts of characters ) as soon as fgetc reaches EOF mark which can be present before the actual end of the file it gets stuck there and stop reading the next characters .
is this some kind of limitation of getc() ? here is my rubbish code
int get_file_size(char filename[])
{
FILE *p_file = NULL;
p_file = fopen(filename,"rb");
fseek(p_file,0,SEEK_END);
int size = ftell(p_file);
fclose(p_file);
return size;
}
int endec(char filename[],char psdw[])
{
FILE *f;
int hashed=0,ed=0;
int inphash=inhash(psdw);
inphash=inphash%50;
f=fopen(filename,"r");
if(f==NULL)
printf("failed");
char temps[999999];
long int crs=0,j=0;
int filesz=get_file_size(filename);
printf("file size = %d\n\n",filesz);
while(1){
inphash=inphash+2;
char ca=(char)inphash;
char ca2=fgetc(f);
printf("%c\n",ca2);
if(crs>=filesz)
break;
temps[crs]= ca2 ^ ca;
crs++;
}
fclose(f);
printf("%d",strlen(temps));
FILE *fp;
fp=fopen(filename,"wt");
for(j=0;j<crs;j++){
putc (temps[j] , fp);
printf("%c",temps[j]);
}
fclose(fp);
}
Your problem is right here:
f=fopen(filename,"r");
You open the file for text reading, not for binary. Your file size function gets it right, but your decoder function does not.
The idiomatic way to read a file character by character using the C-style IO routines is like this:
f = fopen(filename, "rb");
if (!f)
// handle error
int c; // NOTE: int, not char!
while ( (c = fgetc(f)) != EOF )
{
// do something with 'c'
}
This idiom does not require you to get the file size as a separate operation. You can rewrite your XOR "encryption" routine with a simple loop of the above form. It will be much clearer and more concise.
Your entire decoder function could be rewritten as follows: (minus the debug code)
int endec(char filename[], char psdw[])
{
int inphash = inhash(psdw) % 50;
char temp[999999]; // really, should be std::vector<char>
FILE *f;
if ( (f = fopen(filename, "rb")) == NULL )
{
printf("opening for read failed\n");
return -1;
}
size_t crs = 0;
int c;
while ( (c = fgetc(f)) != EOF )
{
inphash += 2;
temp[crs++] = (char)(inphash ^ c);
}
fclose(f);
if ( (f = fopen(filename, "wt")) == NULL )
{
printf("opening for write failed\n");
return -1;
}
if (fwrite(temp, crs, 1, f) != crs)
{
printf("short write\n");
fclose(f);
return -1;
}
fclose(f);
return 0;
}
Not stellar error handling, but it is error handling.
I'm using a large array of floats. After a lot of fiddling I've managed to write it to a binary file. When opening that file at a later time, the reading process only reads a couple of handfuls of floats (according to the return-value of fread(), and it's all values 0.0f). The reading is supposed to put the floats into an (the original) array, and it does not contain the original values.
I'm using Code::Blocks and MinGW doing a program in the 32bit realm on a 64bit pc .. and I'm not very proficient on c/c++ and pointers.
#include<...>
const int mSIZE = 6000 ;
static float data[mSIZE*mSIZE] ;
void myUseFunc(){
const char *chN = "J:/path/flt_632_55.bin" ;
FILE *outFile=NULL ;
# .. sucessfully filling and using data[]
..
size_t st = mSIZE*mSIZE ;
outFile = fopen( chN , "w" ) ;
if(!outFile){ printf("error opening file %s \n", chN); exit(0);}
else{
size_t indt;
indt = fwrite( data , sizeof(float), st , outFile );
std::cout << "floats written to file: " << indt << std::endl ;
#.. value shows that all values ar written
# and a properly sized file has appeared at the proper place
}
fclose( outFile ) ;
}
void myLoadFunc( const char *fileName){
FILE *inFile = NULL ;
inFile = fopen( fileName, "r");
if(!inFile){ printf("error opening file %s \n", fileName); exit(0); }
size_t blok = mSIZE*mSIZE ;
size_t out;
out = fread( dataOne, sizeof(GLfloat), blok , inFile);
fclose(inFile);
if(out != blok){
std::cout<< out << std::endl ;
fputs ("Reading error",stderr);
# no stderr presented at the console ..
printf("some error\n") ;
exit(0);
# .. program exits at out=14
}
...
}
int main( ){
...
const char *FileName = "J:/path/flt_632_55.bin" ;
myLoadFunc( FileName ) ;
...
}
You are not writing to/reading from a binary file, you open the files as text files.
You need to add the "b" to the open mode, like
outFile = fopen( chN , "wb" ) ;
I am writing a XOR encryption program which works fine during encryption but during decryption
the
char ca2=fgetc(f);
gets stuck at one point and no decryption takes place after that my best guess about the problem is (the encrypted file contains all sorts of characters ) as soon as fgetc reaches EOF mark which can be present before the actual end of the file it gets stuck there and stop reading the next characters .
is this some kind of limitation of getc() ? here is my rubbish code
int get_file_size(char filename[])
{
FILE *p_file = NULL;
p_file = fopen(filename,"rb");
fseek(p_file,0,SEEK_END);
int size = ftell(p_file);
fclose(p_file);
return size;
}
int endec(char filename[],char psdw[])
{
FILE *f;
int hashed=0,ed=0;
int inphash=inhash(psdw);
inphash=inphash%50;
f=fopen(filename,"r");
if(f==NULL)
printf("failed");
char temps[999999];
long int crs=0,j=0;
int filesz=get_file_size(filename);
printf("file size = %d\n\n",filesz);
while(1){
inphash=inphash+2;
char ca=(char)inphash;
char ca2=fgetc(f);
printf("%c\n",ca2);
if(crs>=filesz)
break;
temps[crs]= ca2 ^ ca;
crs++;
}
fclose(f);
printf("%d",strlen(temps));
FILE *fp;
fp=fopen(filename,"wt");
for(j=0;j<crs;j++){
putc (temps[j] , fp);
printf("%c",temps[j]);
}
fclose(fp);
}
Your problem is right here:
f=fopen(filename,"r");
You open the file for text reading, not for binary. Your file size function gets it right, but your decoder function does not.
The idiomatic way to read a file character by character using the C-style IO routines is like this:
f = fopen(filename, "rb");
if (!f)
// handle error
int c; // NOTE: int, not char!
while ( (c = fgetc(f)) != EOF )
{
// do something with 'c'
}
This idiom does not require you to get the file size as a separate operation. You can rewrite your XOR "encryption" routine with a simple loop of the above form. It will be much clearer and more concise.
Your entire decoder function could be rewritten as follows: (minus the debug code)
int endec(char filename[], char psdw[])
{
int inphash = inhash(psdw) % 50;
char temp[999999]; // really, should be std::vector<char>
FILE *f;
if ( (f = fopen(filename, "rb")) == NULL )
{
printf("opening for read failed\n");
return -1;
}
size_t crs = 0;
int c;
while ( (c = fgetc(f)) != EOF )
{
inphash += 2;
temp[crs++] = (char)(inphash ^ c);
}
fclose(f);
if ( (f = fopen(filename, "wt")) == NULL )
{
printf("opening for write failed\n");
return -1;
}
if (fwrite(temp, crs, 1, f) != crs)
{
printf("short write\n");
fclose(f);
return -1;
}
fclose(f);
return 0;
}
Not stellar error handling, but it is error handling.
[Fore note: I have read the existing threads in StackOverflow. None seemed to be on my question]
I am looking into the Quake 2 MD2 format. I seem to be getting a bad allocation after new'ing a pointer-array. However, if I do some horrible pointer manipulation, everything is fine.
I guess the question is, why am I getting such an exception?
The first "MD2Model::Load" works. The one I posted after it gets the exception.
Basic structures :
struct MD2Header
{
int nIdentifier;
int nVersion;
int nSkinWidth;
int nSkinHeight;
int nFrameSize;
int nNumSkins;
int nNumVertices;
int nNumUV;
int nNumTriangles;
int nNumCmds;
int nNumFrames;
int nOffsetSkins;
int nOffsetUV;
int nOffSetTriangles;
int nOffsetFrames;
int nOffsetCmds;
int nOffsetEnd;
};
struct MD2Skin
{
char szName[64];
};
struct MD2TexCoord
{
short t;
short u;
};
struct MD2Triangle
{
short nVertex[3];
short tu[3];
};
struct MD2Vertex
{
float fVertex[3];
float fNormal[3];
};
struct MD2Frame
{
char szName[16];
MD2Vertex* pVerts;
};
And now, the function that reads the .md2 file:
bool MD2Model::Load( const char* pszName )
{
FILE* pFile = NULL;
fopen_s( &pFile, pszName, "rb" );
if( !pFile )
return false;
/* Read Header */
fread( &m_Header, sizeof(MD2Header), 1, pFile );
/* Allocate Pointers */
m_pSkins = new MD2Skin[m_Header.nNumSkins];
m_pTexCoords = new MD2TexCoord[m_Header.nNumUV];
m_pTriangles = new MD2Triangle[m_Header.nNumTriangles];
m_pFrames = new MD2Frame[m_Header.nNumFrames];
/* Read Skins */
fseek( pFile, m_Header.nOffsetSkins, SEEK_SET );
fread( m_pSkins, sizeof(MD2Skin), m_Header.nNumSkins, pFile );
/* Read Texture Coords */
fseek( pFile, m_Header.nOffsetUV, SEEK_SET );
fread( m_pTexCoords, sizeof(MD2TexCoord), m_Header.nNumUV, pFile );
/* Read Faces */
fseek( pFile, m_Header.nOffSetTriangles, SEEK_SET );
fread( m_pTriangles, sizeof(MD2Triangle), m_Header.nNumTriangles, pFile );
/* Read Animations */
struct stMD2Vertex
{
unsigned char nVertex[3];
unsigned char nLightNormalIndex;
};
struct stMD2Frame
{
float fScale[3];
float fTranslate[3];
char szName[16];
stMD2Vertex verts[1];
};
unsigned char pBuffer[30000];
stMD2Frame* pTmp = (stMD2Frame*) pBuffer;
fseek( pFile, m_Header.nOffsetFrames, SEEK_SET );
for( int i = 0; i < m_Header.nNumFrames; i++ )
{
fread( pTmp, 1, m_Header.nFrameSize, pFile );
m_pFrames[i].pVerts = new MD2Vertex[m_Header.nNumVertices];
strcpy_s( m_pFrames[i].szName, pTmp->szName );
for( int j = 0; j < m_Header.nNumVertices; j++ )
{
m_pFrames[i].pVerts[j].fVertex[0] = pTmp->verts[j].nVertex[0] *
pTmp->fScale[0] + pTmp->fTranslate[0];
m_pFrames[i].pVerts[j].fVertex[2] = -1 * (pTmp->verts[j].nVertex[1] *
pTmp->fScale[1] + pTmp->fTranslate[1]);
m_pFrames[i].pVerts[j].fVertex[1] = pTmp->verts[j].nVertex[2] *
pTmp->fScale[2] + pTmp->fTranslate[2];
}
}
return true;
}
Variables dumped during debugging:
nNumSkins 1 int
nNumVertices 583 int
nNumUV 582 int
nNumTriangles 422 int
nNumFrames 1 int
(I ended up removing my D3DXVECTOR3 structures to see, so it's kinda fugly..)
Alright. So, inside the 'for' loop, is where it blows up.
If I were to do it like this:
// unsigned char pBuffer[30000];
// stMD2Frame* pTmp = (stMD2Frame*) pBuffer;
fseek( pFile, m_Header.nOffsetFrames, SEEK_SET );
for( int i = 0; i < m_Header.nNumFrames; i++ )
{
stMD2Frame* pTmp = new stMD2Frame();
fread( pTmp, 1, m_Header.nFrameSize, pFile );
m_pFrames[i].pVerts = new MD2Vertex[m_Header.nNumVertices];
strcpy_s( m_pFrames[0].szName, pTmp->szName );
I get the bad_alloc exception during allocating the "m_pFrames[i].pVerts" statement.
Sometimes, I don't get it, but I do get the exception when I try to new my D3D class (I'm assuming I'll get it no matter what I new afterwards).
My MEM usage is extremely low, so could it be heap corruption?
I actually had to end up doing this during creating my VertexBuffer during animations as well.
Should I end up using vectors? I know they allocate more than needed, but it seems like the (most obvious)[best] way.
I would check the line:
strcpy_s( m_pFrames[0].szName, pTmp->szName );
If the string loaded from the file is not null-terminated then this copy could end up overwriting your stack space and causing corruption.
EDIT
Looking again, I think the problem is that you define stMD2Frame as
struct stMD2Frame
{
float fScale[3];
float fTranslate[3];
char szName[16];
stMD2Vertex verts[1];
};
but this only has space for one vertex.
When you read in the frame as
fread( pTmp, 1, m_Header.nFrameSize, pFile );
you will corrupt your memory.
I suggest a check that
sizeof(stMD2Frame)>=m_Header.nFrameSize
before reading the data.
I'm making an HTTP server and when I get the path of the file they request I open it with the following:
returned_file = fopen(path, "r");
this (contrary to what I would think) succeeds even if the path is a directory. Is there an easy way to check if the returned_file stream is a directory instead of a file?
you can use fstat on the file descriptor returned by fopen.
Edit:
Here's and example program:
#include <sys/stat.h>
#include <stdio.h>
void printISDir( FILE* fp, char const * name ) {
int fdes = fileno(fp) ;
struct stat fileInfo ;
fstat(fdes, &fileInfo ) ;
if ( S_ISDIR(fileInfo.st_mode ) ) {
printf("%s: I'm a dir!\n", name ) ;
} else {
printf("%s: I'm a file!\n", name ) ;
}
}
int main( int argc, char** argv ) {
char const * directoryName = "/etc" ;
char const * fileName = "/etc/hosts" ;
FILE* dirFp = fopen(directoryName, "r") ;
FILE* fileFp = fopen(fileName, "r") ;
printISDir( dirFp, directoryName ) ;
printISDir( fileFp, fileName ) ;
fclose(dirFp) ;
fclose(fileFp) ;
return 0 ;
}
Elaborating on the other answers, you can call fstat on the returned file descriptor and check the st_mode for the S_IFDIR bit. The S_ISDIR helper macro is helpful:
#include <sys/stat.h>
...
FILE* f = fopen(path, "r");
struct stat buf;
if (fstat(fileno(f), &buf) == -1) {
perror("fstat");
} else {
if (S_ISDIR(buf.st_mode)) {
printf("is directory\n");
} else {
printf("not directory\n");
}
}
Can you check if the path points to a directory before you call fopen?
Use stat() on the file name before you open it, or fstat() the file descriptor fileno(returned_file).