Possible memory leak in string memory allocation - c++

This is my code:
#include <string>
#include <iostream>
#include <cstdio>
#include <cstdlib>
std::string & fileread(const char * name)
{
FILE *fp = fopen(name,"rb");
size_t sz;
int i;
char *buff;
fseek(fp, 0, SEEK_END);
sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
buff = (char *)malloc(sizeof(char)*(sz+1));
buff[sz] = '\0';
fread(buff,sz,1,fp);
std::string * rtstr = new std::string(buff);
free(buff);
fclose(fp);
return * rtstr;
}
int main(int argc,char * argv[])
{
std::string file_info(fileread(argv[1]));
std::cout<<file_info << std::endl;
return 0;
}
It is simply read one file, and print its content to screen.
In the function fileread, I use new std::string(buff); to get a std::string *, and return the point back. Will it cause memory leak? And if the answer is 'yes' , how to avoid it?
About use C in C++: fread is much faster than ifstream (tested with 1 billion random number)
My problem is about memory leak.

Return std::string by value. Don't worry, C++ will take care of not copying the object redundantly (unless you have a very old compiler).
Here is the code, fixed:
#include <string>
#include <iostream>
#include <cstdio>
#include <cstdlib>
std::string fileread(const char * name)
{
FILE *fp = fopen(name,"rb");
size_t sz;
int i;
char *buff;
fseek(fp, 0, SEEK_END);
sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
buff = (char *)malloc(sizeof(char)*(sz+1));
buff[sz] = '\0';
fread(buff,sz,1,fp);
std::string rtstr(buff);
free(buff);
fclose(fp);
return * rtstr;
}
int main(int argc,char * argv[])
{
std::string file_info(fileread(argv[1]));
std::cout<<file_info << std::endl;
return 0;
}
I made only the small change necessary and ignored any other problems you might have in your code. Take care.

As Nawaz rightly commented: "DONT code C in C++. Use std::ifstream and std::string (not std::string*)". Here is the code in C++ to avoid all the issues:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("myfile.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}

Related

How can I solve this problem, i need to export a line from a text file?

I have an input file like this:
Virtual (A) (A) (A) (A) (A) (A) (A) (A) (A) (A) (A) (A)
The electronic state is 1-A.
Alpha occ. eigenvalues -- -0.26426 -0.26166 -0.25915 -0.25885
Alpha occ. eigenvalues -- -0.25284 -0.25172 -0.24273 -0.23559
Alpha occ. eigenvalues -- -0.20078 -0.19615 -0.17676 -0.10810
Alpha virt. eigenvalues -- -0.07062 -0.06520 -0.05969 -0.01767
Alpha virt. eigenvalues -- -0.01604 -0.00951 -0.00428 0.00041
I would like to export the first line obtaining first 11 characters " Alpha virt.". How should I do? I code by C++ language as below code, but it cant finish while loop functio. I dont know why, I am a fresher. Please help me. Thank you so much.
My C++ code:
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#define FILENAME "filelog.txt"
using namespace std;
int main(void) {
char* line_buf = NULL;
size_t line_buf_size = 0;
int line_count = 0;
string s;
std::string dongsosanh = " Alpha virt.";
FILE* fp = fopen(FILENAME, "r");
getline(&line_buf, &line_buf_size, fp);
std::string STRR(line_buf, 11);
do {
line_count++;
getline(&line_buf, &line_buf_size, fp);
} while(STRR.compare(dongsosanh) != 0);
std::cout << STRR << endl;
return 0;
}
Thank you so much.
Many problems with your program:
line_buf - does not have memory allocated, undef behaviour
line_count - is 0, nothing will be red
You are not closing file at the end.
" Alpha virt." - this line will never be found, it has space at the begining.
STRR is never updated after line has been red, endless loop
Working solution:
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#define FILENAME "filelog.txt"
using namespace std;
int main(void) {
const std::string dongsosanh = "Alpha virt.";
char* line_buf = new char[100];
size_t line_buf_size = 100;
int line_count = 0;
string s;
FILE* fp = fopen(FILENAME, "r");
do {
line_count++;
getline(&line_buf, &line_buf_size, fp);
std::cout << line_buf;
} while(dongsosanh.compare(0, 11, line_buf, 11));
free(line_buf);
fclose(fp);
return 0;
}
This is to show how it works in your case, but you should use vector instead of char* line_buf.
You could just do this:
std::ifstream input(FILENAME);
std::string line;
while(std::getline(input, line)) {
if(line.substr(0, 11) == "Alpha virt.") {
std::cout << line << endl;
return 0;
}
}
EDIT: added the return statement to make sure only the first line starting with 'Alpha virt.' is printed.

Cant copy the whole text file to char array

I am trying to copy a whole text file into char array using fstream but even upon increasing the size of the array it reads the text file to same limit .i am bount to save it in a char array and it will be good if it is not a dynamic one ??? any solution please ...
// smallGrams.cpp : Defines the entry point for the console application.
//
//#include "stdafx.h"
#include<iostream>
using namespace std;
#include<string>
#include<fstream>
void readInput(const char* Path);
void removePunctucationMarks();
void removeSpacing();
void insertDots();
char * getText();
void generateUnigrams();
void generateBigrams();
void generateTrigrams();
double validateSentance(string str);
string sentenceCreation(int position);
int main()
{
char *path="alice.txt";
readInput(path);
return 0;
}
void readInput(const char* Path)
{
ifstream infile;
infile.open(Path);
if(!infile.fail())
cout<<"File opened successfully"<<endl;
else
cout<<"File failed to open"<<endl;
int arrSize=100000000;
char *arr=new char[arrSize];
int i=0;
while(!infile.eof()&&i<arrSize)
{
infile.get(arr[i]);
i++;
}
arr[i-1]='\0';
for(short i=0;i<arrSize&&arr[i]!='\0';i++)
{
cout<<arr[i];
}
}
This is a C style solution that works. It checks the file size and then allocate the necessary memory for the array and reads all the content of the file in one call. The fread() call returns the number of bytes you requested or an error has ocurred (check fread() reference)
# include <cstring>
# include <cstdlib>
# include <cstdio>
int main(int argc, char *argv[]) {
char *data;
int data_len;
FILE *fd;
fd = fopen ("file.txt", "r");
if (fd == NULL) {
// error
return -1;
}
fseek (fd , 0 , SEEK_END);
data_len = ftell (fd);
rewind (fd);
data = (char *) malloc ((data_len + 1) * sizeof (char));
memset (data, data_len + 1, NULL);
if (fread (data, sizeof (char), data_len, fd) != data_len) {
// error
return -1;
}
printf ("%s\n", data);
fclose (fd);
free (data);
return 0;
}
Here with a simple doubling method...
#include<iostream>
#include<string>
#include<fstream>
#include <cstdint>
#include <cstring>
using namespace std;
void readInput(const char* Path)
{
ifstream infile;
infile.open(Path);
if(!infile.fail())
cout<<"File opened successfully"<<endl;
else{
cout<<"File failed to open"<<endl;
return;
}
int capacity=1000;
char *arr=new char[capacity];
char *temp;
int i=0;
while(infile >> arr[i])
{
i++;
if ( i >= capacity ) {
temp = new char[capacity*2];
std::memcpy(temp , arr, capacity);
delete [] arr;
arr = temp;
capacity *=2;
}
}
}
int main()
{
char *path="alice.txt";
readInput(path);
return 0;
}
The error could when you read and display the array content using the for loop and not on reading the data from file.
Use int instead of short in for loop, as short can increment upto 32768, only.

C++ reading a file prints nothing to console

I'm having trouble printing the contents of a file to console.
file.bin contents are "abc".
data holds value, but it just doesn't print it...
#include <Windows.h>
#include <iostream>
int main()
{
wchar_t *data;
FILE* file;
int err = _wfopen_s(&file, L"file.bin", L"rb");
if (err != 0)
{
std::cout << "Error";
return 0;
}
fseek(file, 0, SEEK_END);
long lSize;
lSize = ftell(file);
rewind(file);
data = (wchar_t *)malloc(lSize + 1);
fread(data, 1, lSize, file);
//dereference pointer
wchar_t data2 = *data;
std::wcout << data2; // prints nothing...
system("PAUSE");
return 0;
}
EDIT
I know about fstream but I would really prefer C style opening/reading files.
#include <fstream>
#include <string>
#include <iostream>
int main()
{
std::ifstream ifs("file.bin");
std::string content( (std::istreambuf_iterator<char>(ifs) ),
(std::istreambuf_iterator<char>() ) );
std::cout<<content;
return 0;
}
Use std::ifstream if you're using c++. You're making this much more complicated then you need to. See this former answer.

Hex value comparison and save to file C++

I am reading H.264 bitstream as Hex file in c++. I want to insert some string whenever some certain condition met.Like in the attached image if hex value of 00 00 00 01 occurs anywhere in the file i want to add some string like ABC before 00 00 00 01 in the file and save this as a new file. Write now my approach is to read h.264 file as hex. convert it into string and make a string comparison. if there is a way i can do a straight hex comparison? Here is my current code
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <iomanip>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char x;
string s1,s2,s3;
s2="Mushahid Hussain";
s3="0000000141";
std::ifstream input("d:\\Jm\\videos\\trying2.264", std::ios::binary);
input >> std::noskipws;
while (input >> x) {
long constant = 0x0000000168;
std::ostringstream buffer;
buffer << std::hex << std::setw(2) << std::setfill('0')
<< (int)x;
s1=buffer.str();
if (s1.find(s1) != std::string::npos) {
cout<<"hello";
s1+=s2;
}
std::ofstream outfile;
outfile.open("d:\\Jm\\bin\\trying5.264", std::ios_base::app);
outfile << s1;
}
return 0;
}
Edit 1
As answered by Tommylee2k i am able to append string . But problem is that at the end of file hex CD value is appending like shown in the attached image.
perhaps a better approach is to read the file binary into a memory buffer, and find the memcmp() instead.
When you found your pattern, you write the block ahead of the match, then your "ABC"-string, and continue searching the rest of the file
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
char pattern[4]= { 0x00,0x00,0x01,0x67 };
char *memfind(char *s, int len, char *p, int plen) {
int n=0;
char *pos = s;
while ((pos-s)<(len-plen)) {
while ( *(pos+n) == *(p+n) && n<=plen) n++;
if (n==plen)
return pos;
pos++;n=0;
}
return NULL;
}
int main() {
FILE *in = fopen("in.vid", "r+");
FILE *out = fopen("out.vid", "wb");
// get Filesize
size_t size = 0;
fseek(in, 0L, SEEK_END);
size = ftell(in);
// read whole file in
char *buffer = malloc(size);
fseek (in, 0L, SEEK_SET);
fread (buffer, size, 1, in);
char *currentPos = buffer;
char *found;
if (buffer) {
while (1) {
found = memfind(currentPos, size-(currentPos-buffer), pattern, sizeof(pattern));
if (found==NULL) break;
fwrite(currentPos, 1, (size_t) (found-currentPos), out);
fwrite("ABC", sizeof("ABC"), 1, out);
fwrite(pattern, sizeof(pattern),1,out);
currentPos=found+4;
}
fwrite (currentPos, 1, (size_t) size - (currentPos-buffer), out);
free(buffer);
}
fclose (in);
fclose (out);
return 0;
}

howto: Read input and store it in another file

I want to make a program that reads the highest value from one file and stores it in another. I've read about ifstream and ofstream but how do I let the ofstream store the highest value from the instream in another file? Here is what I have so far:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
struct CsvWhitespace : ctype<char> {
static const mask* make_table() {
static vector<mask> v{classic_table(), classic_table() + table_size};
v[','] |= space; // comma will be classified as whitespace
return v.data();
}
CsvWhitespace(size_t refs = 0) : ctype{make_table(), false, refs} {}
} csvWhitespace;
int main() {
string line;
ifstream myfile ("C:/Users/Username/Desktop/log.csv");
ofstream myfile2 ("C:/Users/Username/Desktop/log2.csv");
return 0;
}
auto v = vector<int>{};
myfile.imbue(locale{myfile.getloc(), &csvWhitespace});
copy(istream_iterator<int>{myfile}, istream_iterator<int>{}, back_inserter(v));
myfile2 << *max_element(begin(v), end(v));
}
Thanks in advance :)
You could just copy from the one file in the other, without having to worry about the format, by treating them in binary mode. Here is an example:
#include <stdio.h>
#include <string.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
FILE *ifp, *ofp;
char buf[bufSize];
if (argc != 3)
{
fprintf(stderr,
"Usage: %s <soure-file> <target-file>\n", argv[0]);
return 1;
}
if ((ifp = fopen(argv[1], "rb")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
if ((ofp = fopen(argv[2], "wb")) == NULL)
{ /* Open target file. */
perror("fopen target-file");
return 1;
}
while (fgets(buf, sizeof(buf), ifp) != NULL)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
/* Write characters read to target file. */
fwrite(buf, sizeof(char), strlen(buf), ofp);
}
fclose(ifp);
fclose(ofp);
return 0;
}
which was given as an example in IP, source. You just need to specify the cmd arguments as the desired files.
You can do it like this. Live example using cin and cout rather than files.
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
struct CsvWhitespace : ctype<char> {
static const mask* make_table() {
static vector<mask> v{classic_table(), classic_table() + table_size};
v[','] |= space; // comma will be classified as whitespace
return v.data();
}
CsvWhitespace(size_t refs = 0) : ctype{make_table(), false, refs} {}
};
int main() {
string line;
ifstream myfile("log.csv");
ofstream myfile2("log2.csv");
auto v = vector<int>{};
myfile.imbue(locale{myfile.getloc(), new CsvWhitespace{}});
copy(istream_iterator<int>{myfile}, istream_iterator<int>{}, back_inserter(v));
myfile2 << *max_element(begin(v), end(v));
}