Here is the source code:
int main() {
int secondsInYear = 366*24*60*60; // Equals 31,622,400
short int data[secondsInYear];
FILE * pFile;
pFile = fopen ("stat", "r");
fread(data, sizeof(short int), secondsInYear, pFile);
fclose(pFile);
}
on line fopen("stat", "r") it gives me the segmentation fault error! If I read secondsInYear/10 characters it will execute without any problem, So what seems to be the problem? And what's the solution?
You're creating a massive array on the stack. So you are hitting a stackoverflow. :)
You should dynamically allocate that array instead.
short int *data = new short int[secondsInYear];
and be sure to delete it later:
delete[] data;
That's way too big to fit the stack (the data array). Use new instead.
short *data = new short[secondsInYear];
After you are done with the array, you should delete [] data if the program continues running.
Not sure if it fits your case but I hear C++ programmers use std::vector instead of plain arrays for most things.
std::vector<short> shorts;
Related
I'm new to C++ and am making an app that uses a lot of putc to write data in output which is file. Because of high writes its being slowed down, I used to code in Delphi, so I know how to solve it, like make a memory stream and write into it every time we need to write into output, and if size of memory stream is larger than buffer size we want, write it into output and clear the memory stream. How should I do this with C++ or any better solution?
putc is already buffered, 4 KB is default you can use setvbuf for changing that value :D
setvbuf
Writing to a file should be very quick. It is usually the emptying of the buffer that takes some time. Consider using the character \n instead of std::endl.
I think a good answer to your question is here: Writing a binary file in C++ very fast
Where the answer is:
#include <stdio.h>
const unsigned long long size = 8ULL*1024ULL*1024ULL;
unsigned long long a[size];
int main()
{
FILE* pFile;
pFile = fopen("file.binary", "wb");
for (unsigned long long j = 0; j < 1024; ++j){
//Some calculations to fill a[]
fwrite(a, 1, size*sizeof(unsigned long long), pFile);
}
fclose(pFile);
return 0;
}
The most important thing in your case is to write as much data you can, with the least possible I/O requests.
My task is to read a yuv file and to each component(Y,Cb,Cr) of it, I'm appending some data and storing it into another file. I have tried the below code:
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp=fopen("traffic_1920x1080.yuv","rb");
FILE *myYUV=fopen("traffic_1920x1088.yuv","ab");
int count=0;
unsigned char *y=(unsigned char*)malloc(sizeof(unsigned char)*1920*1080);
unsigned char *u=(unsigned char*)malloc(sizeof(unsigned char)*(1920/2)*(1080/2));
unsigned char *v=(unsigned char*)malloc(sizeof(unsigned char)*(1920/2)*(1080/2));
unsigned char ypad[1920*8];
unsigned char upad[(1920/2)*4];
unsigned char vpad[(1920/2)*4];
for(int i=0;i<(1920/2)*4;i++)
{
ypad[i]=255;
upad[i]=128;
vpad[i]=128;
}
for(int i=(1920/2)*4;i<1920*8;i++)
ypad[i]=255;
while (!feof(fp))
{
fread(y,sizeof(unsigned char),1920*1080,fp);
fread(u,sizeof(unsigned char),1920/2*1080/2,fp);
fread(v,sizeof(unsigned char),1920/2*1080/2,fp);
fwrite(y, sizeof(unsigned char),1920*1080,myYUV);
fwrite(ypad,sizeof(unsigned char),1920*8,myYUV);
fwrite(u,sizeof(unsigned char),1920/2*1080/2,myYUV);
fwrite(upad,sizeof(unsigned char),1920/2*4,myYUV);
fwrite(v,sizeof(unsigned char),1920/2*1080/2,myYUV);
fwrite(vpad,sizeof(unsigned char),1920/2*4,myYUV);
printf("Frame %d created\r",count);
y+=1920*1080;
u+=1920/2*1080/2;
v+=1920/2*1080/2;
count ++;
}
free(y);
free(u);
free(v);
fclose(fp);
fclose(myYUV);
}
Howevr the above code works fine for the first loop, but in the second loop i get an exception
Access violation writing location 0x0092f000.
at line fwrite(y, sizeof(unsigned char),1920*1080,myYUV);
Is this a problem in pointer increment? or it is something else? Please reply. Thanks in advance.
These increments:
y+=1920*1080;
u+=1920/2*1080/2;
v+=1920/2*1080/2;
will increment the pointers past the end of the allocated memory. For example, y points to the start of 1920*1080 bytes of allocated memory. Increasing it by that much makes it point past the end of that memory. This results in reading/writing to/from unallocated memory. That's why you get an access violation.
I don't actually see a reason for those pointers to be incremented at all.
Other than that, your code should check for error conditions (did fopen() succeed, etc.)
I'm trying to read from a binary file, using fstream, some data I have previously written there.
The problem is that after getting to the end of the function the message in the subject is shown
The code is the following:
ifstream in("contrib.bin", ios::in | ios::binary );
char *nume, dim;
in.read((char*)&dim, sizeof(int));
nume = new char[dim + 1];
in.read(nume, dim);
nume[dim] = '\0';
double imp;
in.read((char*)&imp, sizeof(double));
delete [] nume;
Now, I've done my homework and looked for this issue, but the other people who faced it had arrays, whereas my variable is a simple char.
Can someone point me to the right direction, please?
The code
char dim;
in.read((char*)&dim, sizeof(int));
defines a 1 byte char then reads sizeof(int) bytes (which is likely to be greater that 1) into it. This is invalid and may corrupt your stack.
If you need to read sizeof(int) bytes, declare dim as int. Otherwise, change the number of bytes you read to 1. It'd be best if you also used sizeof(dim) to ensure that you only read as many bytes as you've provided storage for:
in.read((char*)&dim, sizeof(dim));
in.read((char*)&dim, sizeof(int)); is not correct, dim only holds sizeof(char) which is one, but you're attempting to read sizeof(int) into it.
All gloves are off after this.
Well you define a character then read in the size of an int. That would be the first issue
char *nume, dim;
in.read((char*)&dim, sizeof(char));
None of the posted answers I've read work, so I'm asking again.
I'm trying to copy the string data pointed to by a char pointer into a char array.
I have a function that reads from a ifstream into a char array
char* FileReader::getNextBytes(int numberOfBytes) {
char *buf = new char[numberOfBytes];
file.read(buf, numberOfBytes);
return buf;
}
I then have a struct :
struct Packet {
char data[MAX_DATA_SIZE]; // can hold file name or data
} packet;
I want to copy what is returned from getNextBytes(MAX_DATA_SIZE) into packet.data;
EDIT: Let me show you what I'm getting with all the answers gotten below (memcpy, strcpy, passing as parameter). I'm thinking the error comes from somewhere else. I'm reading a file as binary (it's a png). I'll loop while the fstream is good() and read from the fstream into the buf (which might be the data array). I want to see the length of what I've read :
cout << strlen(packet.data) << endl;
This returns different sizes every time:
8
529
60
46
358
66
156
After that, apparently there are no bytes left to read although the file is 13K + bytes long.
This can be done using standard library function memcpy, which is declared in / :
strcpy(packet.data, buf);
This requires file.read returns proper char series that ends with '\0'. You might also want to ensure numberOfBytes is big enough to accommodate the whole string. Otherwise you could possibly get segmentation fault.
//if buf not properly null terminated added a null char at the end
buf[numberofbytes] = "\0"
//copy the string from buf to struc
strcpy(packet.data, buf);
//or
strncpy(packet.data, buf);
Edit:
Whether or not this is being handled as a string is a very important distinction. In your question, you referred to it as a "string", which is what got us all confused.
Without any library assistance:
char result = reader.getNextBytes(MAX_DATA_SIZE);
for (int i = 0; i < MAX_DATA_SIZE; ++MAX_DATA_SIZE) {
packet.data[i] = result[i];
}
delete [] result;
Using #include <cstring>:
memcpy(packet.data, result, MAX_DATA_SIZE);
Or for extra credit, rewrite getNextBytes so it has an output parameter:
char* FileReader::getNextBytes(int numberOfBytes, char* buf) {
file.read(buf, numberOfBytes);
return buf;
}
Then it's just:
reader.getNextBytes(MAX_DATA_SIZE, packet.data);
Edit 2:
To get the length of a file:
file.seekg (0, ios::end);
int length = file.tellg();
file.seekg (0, ios::beg);
And with that in hand...
char* buffer = new char[length];
file.read(buffer, length);
Now you have the entire file in buffer.
strlen is not a valid way to determine the amount of binary data. strlen just reads until it finds '\0', nothing more. If you want to read a chunk of binary data, just use a std::vector, resize it to the amount of bytes you read from the file, and return it as value. Problem solved.
I am trying to read data from binary file, and having issues. I have reduced it down to the most simple case here, and it still won't work. I am new to c++ so I may be doing something silly but, if anyone could advise I would be very grateful.
Code:
int main(int argc,char *argv[]) {
ifstream myfile;
vector<bool> encoded2;
cout << encoded2 << "\n"<< "\n" ;
myfile.open(argv[2], ios::in | ios::binary |ios::ate );
myfile.seekg(0,ios::beg);
myfile.read((char*)&encoded2, 1 );
myfile.close();
cout << encoded2 << "\n"<< "\n" ;
}
Output
00000000
000000000000000000000000000011110000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Compression_Program(58221) malloc: * error for object 0x10012d: Non-aligned pointer being freed
* set a breakpoint in malloc_error_break to debug
Thanks in advance.
Do not cast a vector<bool>* to a char*. It is does not do anything predictable.
You are reading on encoded2: myfile.read((char*)&encoded2, 1 );. this is wrong. you can to read a bool and then put it in encoded2
bool x;
myfile.read( &x, 1 );
encoded2[0] = x;
Two mistakes here:
you assume the address of a vector is the address of the first element
you rely on vector<bool>
Casting a vector into a char * is not really a good thing, because a vector is an object and stores some state along with its elements.
Here you are probably overwriting the state of the vector, thus the destructor of fails.
Maybe you would like to cast the elements of the vector (which are guaranteed to be stored contiguously in memory). But another trap is that vector<bool> may be implementation-optimized.
Therefore you should do a encoded2.reserve(8) and use myfile.read(reinterpret_cast<char *>(&encoded2[0])).
But probably you want to do something else and we need to know what the purpose is here.
You're overwriting a std::vector, which you shouldn't do. A std::vector is actually a pointer to a data array and an integer (probably a size_t) holding its size; if you overwrite these with practically random bits, data corruption will occur.
Since you're only reading a single byte, this will suffice:
char c;
myfile.read(&c, 1);
The C++ language does not provide an efficient I/O method for reading bits as bits. You have to read bits in groups. Also, you have to worry about Endianess when reading int the bits.
I suggest the old fashioned method of allocating a buffer, reading into the buffer then operating on the buffer.
Allocating a buffer
const unsigned int BUFFER_SIZE = 1024 * 1024; // Let the compiler calculate it.
//...
unsigned char * const buffer = new unsigned char [BUFFER_SIZE]; // The pointer is constant.
Reading in the data
unsigned int bytes_read = 0;
ifstream data_file("myfile.bin", ios::binary); // Open file for input without translations.
data_file.read(buffer, BUFFER_SIZE); // Read data into the buffer.
bytes_read = data_file.gcount(); // Get actual count of bytes read.
Reminders:
delete the buffer when you are
finished with it.
Close the file when you are finished
with it.
myfile.read((char*) &encoded2[0], sizeof(int)* COUNT);
or you can use push_back();
int tmp;
for(int i = 0; i < COUNT; i++) {
myfile.read((char*) &tmp, 4);
encoded2.push_back(tmp);
}