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.)
Related
I want to binary read a photo in 1460 bytes increments and compare consecutive packets for corrupted transmission. I have a python script that i wrote and want to translate in C++, however I'm not sure that what I intend to use is correct.
for i in range(0, fileSize-1):
buff=f.read(1460) // buff stores a packet of 1460 bytes where f is the opened file
secondPacket=''
for j in buff:
secondPacket+="{:02x}".format(j)
if(secondPacket==firstPacket):
print(f'Packet {i+1} identical with {i}')
firstPacket=secondPacket
I have found int fseek ( FILE * stream, long int offset, int origin ); but it's unclear if it reads the first byte that is located offset away from origin or everything in between.
Thanks for clarifications.
#include <iostream>
#include <fstream>
#include <array>
std::array<char, 1460> firstPacket;
std::array<char, 1460> secondPacket;
int i=0;
int main() {
std::ifstream file;
file.open("photo.jpg", std::ios::binary);
while (file.read(firstPacket.data(), firstPacket.size())){
++i;
if (firstPacket==secondPacket)
std::cout<<"Packet "<<i<<" is a copy of packet "<<i-1<<std::endl;
memcpy(&secondPacket, &firstPacket, firstPacket.size());
}
std::cout<<i; //tested to check if i iterate correctly
return 0;
}
This is the code i have so far which doesn't work.
fseek
doesn't read, it just moves the point where the next read operation should begin. If you read the file from start to end you don't need this.
To read binary data you want the aptly named std::istream::read. You can use it like this wih a fixed size buffer:
// char is one byte, could also be uint8_t, but then you would need a cast later on
std::array<char, 1460> bytes;
while(myInputStream.read(bytes.data(), bytes.size())) {
// do work with the read data
}
I want to write code that causes a buffer overflow. Could you give me some advice on why my test code below does not cause a buffer overflow?
I think a buffer overflow should occur on this line:
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
#define buffer_size 10
int main(){
string m_string = "My name is String";
char* node_reference = new char[buffer_size];
unsigned int len = strlen(m_string.c_str());
unsigned int buffer_len = sizeof(node_reference)/sizeof(char);
std::printf("len: %d\n", len);
std::printf("buffer len: %d\n", buffer_len);
for (unsigned int i = 0; i < strlen(m_string.c_str()) + 1; i++) {
node_reference[i] = m_string[i];
std::printf("index: %d and value: %c\n", i, node_reference[i]);
}
return 0;
}
EDIT
I removed typo de_referece line. Thank you for your kind answers to the insufficient questions.
sizeof(node_reference) does not do what you think it does, since node_reference is allocated dynamically. You are obtaining the size of the pointer itself, not the size of the allocated buffer being pointed at. Your printf() of buffer_len should have indicated that to you. sizeof(node_reference) would work only if node_reference had been allocated statically instead.
That being said, your code does cause a buffer overflow. You are allocating 10 bytes for node_reference and then writing 18 bytes into it. The behavior is undefined, so anything can happen. A crash is not guaranteed, if that is what you are expecting. You are certainly corrupting memory, though it may not be memory you would normally see since it is outside of your allocation.
I am attempting to compile and run a test C program in Xcode. This program reads 5 symbols from a text file and closes it. The program builds successfully, but when I try to run the program I get the error: GDB: Program received signal: "EXC_BAD_ACCESS" around fclose(in).
#include <iostream>
#include <unistd.h>
int main (int argc, const char * argv[])
{
bool b;
char inpath[PATH_MAX];
printf("Enter input file path :\r\n");
std::cin >> inpath;
FILE *in = fopen(inpath, "r+w");
char buf[5];
fread(&buf,sizeof(buf),5,in);
printf(buf);
fclose(in);
return 0;
}
What could be a cause of this?
Ah! sizeof(buf) will return 5, so you're asking for 25 bytes in a 5-byte buffer. This overwrites auto storage and clobbers in.
And, of course, note that fprint(buf) will be attempting to print a buffer with no terminating null, so it will print garbage beyond the end of what was read.
The line
fread(&buf,sizeof(buf),5,in);
is wrong: read carefully the man page of fread (and remember that sizeof(buf) would be the size of the whole buf array).
The line
printf(buf);
is wrong. Behavior is undefined if for instance buf would contain %d
You definitely should learn to use the debugger (and enable all warnings with your compiler).
fread(&buf,sizeof(buf),5,in);
this says that you want to read the buf 5 times, which is not correct.
The second and third parameters tell fread the size of each element you want to read and the number of elements.
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;
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);
}