segmentation fault while copying a file - c++

I have below simple code , but when I compile and run with GCC on unix, I got segmentation error. Is it because file naming or copying one file to others. Any help appreciated..
#include <iostream>
#include <stdio.h>
using namespace std;
void copy(char *infile, char *outfile) {
FILE *ifp; /* file pointer for the input file */
FILE *ofp; /* file pointer for the output file */
int c; /* character read */
/* open i n f i l e for reading */
ifp = fopen (infile , "r" );
/* open out f i l e for writing */
ofp = fopen(outfile, "w");
/* copy */
while ( (c = fgetc(ifp)) != EOF) /* read a character */
fputc (c, ofp); /* write a character */
/* close the files */
fclose(ifp);
fclose(ofp);
}
main()
{
copy("A.txt","B.txt");
}

The code which you have posted is correct
ifp = fopen (infile , "r" ); //will return NULL if file not there
while ( (c = fgetc(ifp)) != EOF)
The moment you are using , Here is a possibility if you do not have A.txt file in your current directory then you will get segmentation fault.

IF A.txt does not exist, the value of ifp will be NULL (0). Then, this function call will segfault.
fgetc(ifp)
So, change your code to check for NULL on the file opens (each file), for example:
ifp = fopen (infile , "r" );
if (ifp == NULL) {
printf("Could not open %s\n", infile);
exit(-2);
}
You may have to add this include also at the top of your file:
#include <stdlib.h>

Use copy(const char* infile, const char* outfile) in arguments to avoid unnecessary warnings.
Also your files may not be in the current directory in which you are executing code. So give complete path to your file.

Related

Passing a char array reading from file to fopen() generating error as Invalid arguments

I tried to read file path and name into a char array from a configuration.txt file. Then passing the char array to fopen(). However, it is generating errors like invalid argument. Instead, if I directly passed the path same to what is in configuration.txt, it will succeed. The code is like:
FILE *FIDConfig = fopen(argv[1],"r"); // open configuration file; could be a .txt file
char inputfname[200], backgroundfname[200], outputfname[200];
fscanf(FIDConfig, "%s", inputfname); //int fscanf ( FILE * stream, const char * format, ... );
fscanf(FIDConfig, "%s", backgroundfname);
fscanf(FIDConfig, "%s", outputfname);
/* FILE WITH THE RAW DATA */
errno = 0;
FILE *FIDIN, *FIDOUT, *FIDBack; // inputfname = "./data.bin", backgroundfname = "./dbk.bin";
FIDIN = fopen(inputfname, "rb"); // if changed to FIDIN("./data.bin","rb") it works!
FIDBack = fopen(backgroundfname, "rb");

save recursion output to text file

I am trying to recursively list the files in a directory. However when I save the output to a text file, it works, but the file contents keep being reset. So the file size will be 2Kb, and then it is reset to 1Kb, 30Kb reset to 1Kb, and so on. The code is not saving all the output to the text file and only some of the last lines are saved to output.txt.
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <Psapi.h>
#include <fstream>
using namespace std;
void listDir(wchar_t * szCurrentDirectory);
int main()
{
// return current directory where app run
DWORD nBufferLength = MAX_PATH;
wchar_t szCurrentDirectory[MAX_PATH];
GetCurrentDirectory(nBufferLength, szCurrentDirectory);
listDir(szCurrentDirectory);
system("pause");
return 0;
}
void listDir(wchar_t * szCurrentDirectory)
{
wchar_t addPath[MAX_PATH] = L"\\*";
WIN32_FIND_DATA FindFileData;
wchar_t buf[MAX_PATH];
swprintf(buf, MAX_PATH,L"%s%s", szCurrentDirectory, addPath);
HANDLE hFind;
hFind = FindFirstFile(buf, &FindFileData);
wofstream myfile("c:/output.txt");
if (myfile.is_open())
{
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// Check if is a folder or not.
if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_REPARSE_POINT)
{
// Ignore current folder and parent folder.
if (wcscmp(FindFileData.cFileName, L".") && wcscmp(FindFileData.cFileName, L"..") != 0)
{
if (wcscmp(FindFileData.cFileName, L"$RECYCLE.BIN") != 0)
{
// return current directory where app run
wchar_t filepath[10000];
// Append slash to current directory.
swprintf(filepath, 10000, L"%s%s%s", szCurrentDirectory, L"\\", FindFileData.cFileName);
// Output the file.
myfile << filepath << endl;
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// Recursive
listDir(filepath);
} // if directory
} // if not recycle bin
} // if not . or ..
} if not reparse point
} while (FindNextFile(hFind, &FindFileData) != 0);
FindClose(hFind);
myfile.close();
}
}
}
try to run the app in c: drive and look the output in output.txt. the output keep reset.
Pass the open file as a parameter instead.
Change
void listDir(wchar_t * szCurrentDirectory)
to
void listDir(wofstream & myfile,wchar_t * szCurrentDirectory)
then remove the file opening code from listDir().
Delete this line:
wofstream myfile("c:/output.txt");
And then call it in main() like this:
wofstream myfile("c:/output.txt");
listDir(myfile,szCurrentDirectory);
And finally in listDir() change
listDir(filepath);
to
listDir(myfile,filepath);
The right answer is definitely to open the file once (in the main program), and then pass the stream into into the listdir function.
However ... there is an alternative. It is not appropriate in this case, it might be in similar cases. You can open the file in append mode, so the contents is never overwritten. You just need to change the line where you open the file to:
std::wofstream myfile("c:/output.txt", std::ios_base::app);
The output will be written to the end of the file, preserving the existing contents.
Open the file in main and pass the handle as a second parameter to the listDir function.
Don't open it in listDir

fwrite() fails without writing anything to existing file

Sorry for this basic problem guys, but I'm having an issue just getting fwrite() to work properly?
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main() {
FILE* fd = NULL;
fd = fopen("out","rw");
if (fd == NULL) {
printf("Open failed\n");
return -1;
}
int error = 0;
printf("Attempting write ... \n");
char buff[] = {"hello?\n"};
if( (error = fwrite(buff, 1, 7, fd)) != 7 ) {
printf("fwrite() failed with code %d \n", error);
return -1;
}
fclose(fd);
return 0;
}
This code fails - fwrite() just returns 0 when it should return 7 instead for seven 1b characters written to the file. The file does exist in the same directory; I've tried this with the full file path instead; I've chmod'd the output file out to 777 in case that was the issue (it wasn't); fread() and fseek() both work as expected but I've taken them out for brevity.
What am I doing wrong here? Any help is appreciated.
fopen do not have "rw" mode, and you should open the file in binary mode since you fwrite to it.
What you want is "wb", "w+b" or "r+b"
fd = fopen("out","rw");
"rw" is not one of the valid open modes.
See the fopen(3) manual page for more information.
You did not specify your platform, or C library. On Linux, this fopen() call fails.

C++ fwrite doesn't write to text file, have no idea why?

I have this code that basically reads from file and creates new file and write the content from the source to the destination file. It reads the buffer and creates the file, but fwrite
doesn't write the content to the newly created file, I have no idea why.
here is the code. (I have to use only this with _sopen, its part of legacy code)
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <share.h>
#include <sys\stat.h>
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
FILE* pfFile;
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
pfFile = fdopen(iFileId, "r");
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
// buffer = (char*) malloc (sizeof(char)*lSize);
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL)
{
return false;
}
// copy the file into the buffer:
result = fread (buffer,lSize,1,pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile );
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
return 0;
}
You can make main file and try it see if its working for you .
Thanks
Change your code to the following and then report your results:
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
{
FILE* pfFile;
if ((pfFile = fdopen(iFileId, "r")) != (FILE *)NULL)
{
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
if ((buffer = (char*) malloc (lSize)) == NULL)
return false;
// copy the file into the buffer:
result = fread (buffer,(size_t)lSize,1,pfFile);
fclose(pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
{
if ((pDesfFile = fdopen(iFileId2, "w+")) != (FILE *)NULL)
{
size_t f = fwrite (buffer, (size_t)lSize, 1, pDesfFile);
printf ("elements written <%d>\n", f);
if (f == 0)
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
}
}
}
}
return 0;
}
[edit]
for other posters, to show the usage/results of fwrite - what is the output of the following?
#include <stdio.h>
int main (int argc, char **argv) {
FILE *fp = fopen ("f.kdt", "w+");
printf ("wrote %d\n", fwrite ("asdf", 4, 1, fp));
fclose (fp);
}
[/edit]
sizeof(buffer) is the size of the pointer, i.e. 4 and not the number of items in the buffer
If buffer is an array then sizeof(buffer) would potentially work as it returns the number of bytes in the array.
The third parameter to fwrite is sizeof(buffer) which is 4 bytes (a pointer). You need to pass in the number of bytes to write instead (lSize).
Update: It also looks like you're missing the flag indicating the file should be Read/Write: _O_RDWR
This is working for me...
std::string szdes = "C:\\temp\\test_des.txt";
FILE* pDesfFile;
int iFileId2;
err = _sopen_s(&iFileId2, szdes.c_str(), _O_CREAT|_O_BINARY|_O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = _fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, lSize, pDesfFile );
fclose (pDesfFile);
Since I can't find info about _sopen, I can only look at man open. It reports:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Your call _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE); doesn't match either one of those, you seem to have flags and 'something' and modes / what is SH_DENY?
What is the result of man _sopen?
Finally, shouldn't you close the file descriptor from _sopen after you fclose the file pointer?
Your final lines should look like this, btw :
if (iFileId2 >= 0)
{
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile ); //<-- the f returns me 4
fclose (pDesfFile);
}
Since you currently write the file regardless of whether or not the fdopen after the O_CREAT succeeded. You also do the same thing at the top, you process the read (and the write) regardless of the success of the fdopen of the RDONLY file :(
You are using a mixture of C and C++. That is confusing.
The sizeof operator does not do what you expect it to do.
Looks like #PJL and #jschroedl found the real problem, but also in general:
Documentation for fwrite states:
fwrite returns the number of full items actually written, which may be less than count if an error occurs. Also, if an error occurs, the file-position indicator cannot be determined.
So if the return value is less than the count passed, use ferror to find out what happened.
The ferror routine (implemented both as a function and as a macro) tests for a reading or writing error on the file associated with stream. If an error has occurred, the error indicator for the stream remains set until the stream is closed or rewound, or until clearerr is called against it.

Why do I get a 'ÿ' char after every include that is extracted by my parser? - C

I have this function:
/*This func runs *.c1 file, and replace every include file with its content
It will save those changes to *.c2 file*/
void includes_extractor(FILE *c1_fp, char *c1_file_name ,int c1_file_str_len )
{
int i=0;
FILE *c2_fp , *header_fp;
char ch, *c2_file_name,header_name[80]; /* we can assume line length 80 chars MAX*/
char inc_name[]="include";
char inc_chk[INCLUDE_LEN+1]; /*INCLUDE_LEN is defined | +1 for null*/
/* making the c2 file name */
c2_file_name=(char *) malloc ((c1_file_str_len)*sizeof(char));
if (c2_file_name == NULL)
{
printf("Out of memory !\n");
exit(0);
}
strcpy(c2_file_name , c1_file_name);
c2_file_name[c1_file_str_len-1] = '\0';
c2_file_name[c1_file_str_len-2] = '2';
/*Open source & destination files + ERR check */
if( !(c1_fp = fopen (c1_file_name,"r") ) )
{
fprintf(stderr,"\ncannot open *.c1 file !\n");
exit(0);
}
if( !(c2_fp = fopen (c2_file_name,"w+") ) )
{
fprintf(stderr,"\ncannot open *.c2 file !\n");
exit(0);
}
/*next code lines are copy char by char from c1 to c2,
but if meet header file, copy its content */
ch=fgetc(c1_fp);
while (!feof(c1_fp))
{
i=0; /*zero i */
if (ch == '#') /*potential #include case*/
{
fgets(inc_chk, INCLUDE_LEN+1, c1_fp); /*8 places for "include" + null*/
if(strcmp(inc_chk,inc_name)==0) /*case #include*/
{
ch=fgetc(c1_fp);
while(ch==' ') /* stop when head with a '<' or '"' */
{
ch=fgetc(c1_fp);
} /*while(2)*/
ch=fgetc(c1_fp); /*start read header file name*/
while((ch!='"') && (ch!='>')) /*until we get the end of header name*/
{
header_name[i] = ch;
i++;
ch=fgetc(c1_fp);
}/*while(3)*/
header_name[i]='\0'; /*close the header_name array*/
if( !(header_fp = fopen (header_name,"r") ) ) /*open *.h for read + ERR chk*/
{
fprintf(stderr,"cannot open header file !\n");
exit(0);
}
while (!feof(header_fp)) /*copy header file content to *.c2 file*/
{
ch=fgetc(header_fp);
fputc(ch,c2_fp);
}/*while(4)*/
fclose(header_fp);
}
}/*frst if*/
else
{
fputc(ch,c2_fp);
}
ch=fgetc(c1_fp);
}/*while(1)*/
fclose(c1_fp);
fclose(c2_fp);
free (c2_file_name);
}
This function reads a single *.c1 file and saves a copy of it to *.c2 file, but all the include files from *.c1 file are extracted and their contents expanded in *.c2.
After every include file that is extracted, I get 'ÿ' sign.
The include can contain 1 line or 1000 lines, but the 'ÿ' sign will appear only once after each include that is extracted.
Can't find why...
"ÿ" corresponds to the code point 0xFF. fgetc returns EOF when the end of file is reached, which is (usually) defined as -1. Store -1 in a char and you'll wind up with 0xFF. You must check for EOF between calling fgetc and fpuc.
int ch;
...
/*copy header file content to *.c2 file*/
for (ch=fgetc(header_fp); ch > -1; ch=fgetc(header_fp)) {
fputc(ch,c2_fp);
}
Instead of getting characters one at a time, you could use fgets to get a block of characters.
#ifndef BUFSIZE
# define BUFSIZE 1024
#endif
char buf[BUFSIZE], *read;
...
/*copy header file content to *.c2 file*/
while ((read = fgets(buf, BUFSIZE, header_fp))) {
fputs(buf, c2_fp);
}
You major problem is this loop.
while (!feof(header_fp)) /*copy header file content to *.c2 file*/
{
ch=fgetc(header_fp);
fputc(ch,c2_fp);
}/*while(4)*/
When fgetc encounters the end of file, it will return EOF, which is a negative integer. You store this in a char and then without checking write it out to the other file.
feof is very rarely useful as a loop condition. Most of the time it is better to check the return value of a read function.
You should always store to return value of fgetc in an int so that you can check the return value for errors (either an end-of-file condition or some other error). fputc takes in int, in any case.
A better way to construct the loop would be as follows.
int ch_hdr;
while((ch_hdr = fgetc(header_fp)) != EOF)
{
fputc(ch_hdr, c2_fp);
}
If you look at your code you have to places where you write to the target file.
If I were you I would set a break point at
}/*frst if*/
else
{
fputc(ch,c2_fp); // brk point here
}
to check what you are actually writing there.