We added some new code in our PNG decoding routines for our game engine. The additional chunk defined is just there to read some values -- no big deal.
On Visual C++, it compiles just fine. On GCC, which is what we primarily use, we now get a strange issue that has never happened before:
compile_problems
This is the added code:
/* read grAb chunk */
png_unknown_chunk *unknowns;
int num_unknowns = png_get_unknown_chunks(png_ptr, info_ptr, &unknowns);
for (int i = 0; i < num_unknowns; i++)
{
if (!memcmp(unknowns[i].name, "grAb", 4))
{
png_grAb_t *grAb = reinterpret_cast<png_grAb_t *>(unknowns[i].data);
grAb->x = EPI_BE_S32(grAb->x) + 160 - width / 2;
grAb->y = EPI_BE_S32(grAb->y) + 200 - 32 - height;
img->grAb = grAb;
break;
}
}
Looks just fine to me. This is the only thing added to our original file. The complete file is here:
goto Line 59 of image_data.cc
And the function where this bombs out:
image_data_c *PNG_Load(file_c *f, int read_flags)
I don't understand what could be happening, as this worked perfectly fine before and never had issue with cross-initialization or our case handling.
If I could get some help, I would really appreciate it!
The errors seem pretty clear: there are jumps to label failed: from before the initialization of int num_unknowns to after it, so that int will have garbage values. This is forbidden in C++ ( but not in C).
One solution is to put
int num_unknowns = 0;
at the beginning of the function, and change the third line of the code sample you posted to just an assignment to num_unknowns.
Another solution is to instruct GCC to allow this, with the -fpermissive option, as the error itself indicates.
Related
I am new to c++ programming and StackOverflow, but I have some experience with core Java. I wanted to participate in programming Olympiads and I choose c++ because c++ codes are generally faster than that of an equivalent Java code.
I was solving some problems involving recursion and DP at zonal level and I came across this question called Sequence game
But unfortunately my code doesn't seem to work. It exits with exit code 3221225477, but I can't make anything out of it. I remember Java did a much better job of pointing out my mistakes, but here in c++ I don't have a clue of what's happening. Here's the code btw,
#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
int N, minimum, maximum;
set <unsigned int> result;
vector <unsigned int> integers;
bool status = true;
void score(unsigned int b, unsigned int step)
{
if(step < N)
{
unsigned int subtracted;
unsigned int added = b + integers[step];
bool add_gate = (added <= maximum);
bool subtract_gate = (b <= integers[step]);
if (subtract_gate)
subtracted = b - integers[step];
subtract_gate = subtract_gate && (subtracted >= minimum);
if(add_gate && subtract_gate)
{
result.insert(added);
result.insert(subtracted);
score(added, step++);
score(subtracted, step++);
}
else if(!(add_gate) && !(subtract_gate))
{
status = false;
return;
}
else if(add_gate)
{
result.insert(added);
score(added, step++);
}
else if(subtract_gate)
{
result.insert(subtracted);
score(subtracted, step++);
}
}
else return;
}
int main()
{
ios_base::sync_with_stdio(false);
ifstream input("input.txt"); // attach to input file
streambuf *cinbuf = cin.rdbuf(); // save old cin buffer
cin.rdbuf(input.rdbuf()); // redirect cin to input.txt
ofstream output("output.txt"); // attach to output file
streambuf *coutbuf = cout.rdbuf(); // save old cout buffer
cout.rdbuf(output.rdbuf()); // redirect cout to output.txt
unsigned int b;
cin>>N>>b>>minimum>>maximum;
for(unsigned int i = 0; i < N; ++i)
cin>>integers[i];
score(b, 0);
set<unsigned int>::iterator iter = result.begin();
if(status)
cout<<*iter<<endl;
else
cout<<-1<<endl;
cin.rdbuf(cinbuf);
cout.rdbuf(coutbuf);
return 0;
}
(Note: I intentionally did not use typedef).
I compiled this code with mingw-w64 in a windows machine and here is the Output:
[Finished in 19.8s with exit code 3221225477] ...
Although I have an intel i5-8600, it took so much time to compile, much of the time was taken by the antivirus to scan my exe file, and even sometimes it keeps on compiling for long without any intervention from the anti-virus.
(Note: I did not use command line, instead I used used sublime text to compile it).
I even tried tdm-gcc, and again some other peculiar exit code came up. I even tried to run it on a Ubuntu machine, but unfortunately it couldn't find the output file. When I ran it on a Codechef Online IDE, even though it did not run properly, but the error message was less scarier than that of mingw's.
It said that there was a run-time error and "SIGSEGV" was displayed as an error code. Codechef states that
A SIGSEGV is an error(signal) caused by an invalid memory reference or
a segmentation fault. You are probably trying to access an array
element out of bounds or trying to use too much memory. Some of the
other causes of a segmentation fault are : Using uninitialized
pointers, dereference of NULL pointers, accessing memory that the
program doesn’t own.
It's been a few days that I am trying to solve this, and I am really frustrated by now. First when i started solving this problem I used c arrays, then changed to vectors and finally now to std::set, while hopping that it will solve the problem, but nothing worked. I tried a another dp problem, and again this was the case.
It would be great if someone help me figure out what's wrong in my code.
Thanks in advance.
3221225477 converted to hex is 0xC0000005, which stands for STATUS_ACCESS_VIOLATION, which means you tried to access (read, write or execute) invalid memory.
I remember Java did a much better job of pointing out my mistakes, but here in c++ I don't have a clue of what's happening.
When you run into your program crashing, you should run it under a debugger. Since you're running your code on Windows, I highly recommend Visual Studio 2017 Community Edition. If you ran your code under it, it would point exact line where the crash happens.
As for your crash itself, as PaulMcKenzie points out in the comment, you're indexing an empty vector, which makes std::cin write into out of bounds memory.
integers is a vector which is a dynamic contiguous array whose size is not known at compile time here. So when it is defined initially, it is empty. You need to insert into the vector. Change the following:
for(unsigned int i = 0; i < N; ++i)
cin>>integers[i];
to this:
int j;
for(unsigned int i = 0; i < N; ++i) {
cin>> j;
integers.push_back(j);
}
P.W's answer is correct, but an alternative to using push_back is to pre-allocate the vector after N is known. Then you can read from cin straight into the vector elements as before.
integers = vector<unsigned int>(N);
for (unsigned int i = 0; i < N; i++)
cin >> integers[i];
This method has the added advantage of only allocating memory for the vector once. The push_back method will reallocate if the underlying buffer fills up.
I'm trying to write a program to check if a number between 1 and 9999999 is a number whose digits either stay the same or increases from left to right(The variable and function names are in Vietnamese)
#include<stdio.h>
int daykhonggiam(int n)
{
while (n>=10)
{
int donvi=n%10;
n=n/10;
if(donvi<n%10)
{
return 0;
}
}
return 1;
}
int main(void)
{
for(int i=1;i<=9999999;i++)
{
if(daykhonggiam(i)==1)
printf("%d\n",i);
}
}
The problem is, when i compile and run the code ,only some of the results were shown( the results from 5555999 to 9999999 ). when i hit f9 i can the the results run from 1 but the final screen only shows from 5555999 to 9999999. I tried an online compiler and all the results were shown.
So i guessing my dev c++ 5.11 is the problem here. Is there any chance any of you know why that's the case ?
It looks like printf just fills console buffer completely and old lines get removed. Try writing results to file or increase console buffer capacity somehow.
Open your terminal, click the top left corner, go to properties, and increase your buffer size. Save, and test. Repeat if needed.
That being said, I concur with previous comments that you should just use an output file.
Edit: After some testing, I could only get a max number of 9,000 lines to display concurrently. I'd pursue using an output file in your case.
I have no experience in audio programming and C++ is quite low level language so I have a little problems with it. I work with ASIO SDK 2.3 downloaded from http://www.steinberg.net/en/company/developers.html.
I am writing my own host based on example inside SDK.
For now I've managed to go through the whole sample and it looks like it's working. I have external sound card connected to my PC. I've successfully loaded driver for this device, configured it, handled callbacks, casting data from analog to digital etc. common stuff.
And part where I am stuck now:
When I play some track via my device I can see bars moving in the mixer (device's software). So device is connected in right way. In my code I've picked the inputs and outputs with the names of the bars that are moving in mixer. I've also used ASIOCreateBuffers() to create buffer for each input/output.
Now correct me if I am wrong:
When ASIOStart() is called and driver is in running state, when I input the sound signal to my external device I believe the buffers get filled with data, right?
I am reading the documentation but I am a bit lost - how can I access the data being sent by device to application, stored in INPUT buffers? Or signal? I need it for signal analysis or maybe recording in future.
EDIT: If I had made it to complicated then in a nutshell my question is: how can I access input stream data from code? I don't see any objects/callbacks letting me to do so in documentation.
The hostsample in the ASIO SDK is pretty close to what you need. In the bufferSwitchTimeInfo callback there is some code like this:
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
int ch = asioDriverInfo.bufferInfos[i].channelNum;
if (asioDriverInfo.bufferInfos[i].isInput == ASIOTrue)
{
char* buf = asioDriver.bufferInfos[i].buffers[index];
....
Inside of that if block asioDriver.bufferInfos[i].buffers[index] is a pointer to the raw audio data (index is a parameter to the method).
The format of the buffer is dependent upon the driver and that can be discovered by testing asioDriverInfo.channelInfos[i].type. The types of formats will be 32bit int LSB first, 32bit int MSB first, and so on. You can find the list of values in the ASIOSampleType enum in asio.h. At this point you'll want to convert the samples to some common format for downstream signal processing code. If you're doing signal processing you'll probably want convert to double. The file host\asioconvertsample.cpp will give you some idea of what's involved in the conversion. The most common format you're going to encounter is probably INT32 MSB. Here is how you'd convert it to double.
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
int ch = asioDriverInfo.bufferInfos[i].channelNum;
if (asioDriverInfo.bufferInfos[i].isInput == ASIOTrue)
{
switch (asioDriverInfo.channelInfos[i].type)
{
case ASIOInt32LSB:
{
double* pDoubleBuf = new double[_bufferSize];
for (int i = 0 ; i < _bufferSize ; ++i)
{
pDoubleBuf[i] = *(int*)asioDriverInfo.bufferInfos.buffers[index] / (double)0x7fffffff;
}
// now pDoubleBuf contains one channels worth of samples in the range of -1.0 to 1.0.
break;
}
// and so on...
Thank you very much. Your answer helped quite much but as I am inexperienced with C++ a bit :P I find it a bit problematic.
In general I've written my own host based on hostsample. I didn't implement asioDriverInfo structure and use common variables for now.
My first problem was:.
char* buf = asioDriver.bufferInfos[i].buffers[index];
as I got error that I can't cast (void*) to char* but this probably solved the problem:
char* buf = static_cast<char*>(bufferInfos[i].buffers[doubleBufferIndex]);
My second problem is with the data conversion. I've checked the file you've recommended me but I find it a little black magic. For now I am trying to follow your example and:
for (int i = 0; i < inputBuffers + outputBuffers; i++)
{
if (bufferInfos[i].isInput)
{
switch (channelInfos[i].type)
{
case ASIOSTInt32LSB:
{
double* pDoubleBuf = new double[buffSize];
for (int j = 0 ; j < buffSize ; ++j)
{
pDoubleBuf[j] = bufferInfos[i].buffers[doubleBufferIndex] / (double)0x7fffffff;
}
break;
}
}
}
I get error there:
pDoubleBuf[j] = bufferInfos[i].buffers[doubleBufferIndex] / (double)0x7fffffff;
which is:
error C2296: '/' : illegal, left operand has type 'void *'
What I don't get is that in your example there is no table there: asioDriverInfo.bufferInfos.buffers[index] after bufferInfos and even if I fix it... to what kind of type should I cast it to make it work. P
PS. I am sure ASIOSTInt32LSB data type is fine for my PC.
The ASIO input and output buffers are accessible using void pointers, but using memcpy or memmove to access I/O buffer will create a memory copy which is to be avoided if you are doing real-time processing. I would suggest casting the pointer type to int* so you can directly access them.
It's also very slow in real-time processing to cast types 1 by 1 when you have like 100+ audio channels when AVX2 is supported on most CPUs.
_mm256_loadu_si256() and _mm256_cvtepi32_ps() will do the conversion much faster.
I'm writing a small utility to parse xfs filesystem on windows.
For small size image <5GB my utility is working fine: I'm able to list all files and directories.
But when I try to parse large xfs image > 30GB. It is giving wrong results.
I'm using _fseeki64 and _ftelli64 for seeking and fread for reading particular block.
One of thing I've notice is that _fseeki64 is not wroking properly.
Below is my seek function which seek to particular group number and block number.
int FileSystemReadXFS::SeekToGroupBlock(uint16_t grpNum, uint64_t blockNum)
{
int error = -1;
//Seek to beginning
if(_fseeki64(m_fileSystemInfo.fp, (__int64)0, SEEK_SET) != 0)
{
PRINT_SEEK_ERROR;
goto BAILOUT;
}
__int64 currPtr = 0;
//Seek to destination group
if(grpNum > 0)
{
if(_fseeki64(m_fileSystemInfo.fp, (__int64)(grpNum*m_fileSystemInfo.SizeOfBlockGroup*m_fileSystemInfo.BlockSize), SEEK_SET))
{
PRINT_SEEK_ERROR;
goto BAILOUT;
}
currPtr = _ftelli64(m_fileSystemInfo.fp);
}
//Seek to destination block in group
if(blockNum > 0)
{
if(_fseeki64(m_fileSystemInfo.fp, (__int64)(blockNum*m_fileSystemInfo.BlockSize), SEEK_CUR))
{
PRINT_SEEK_ERROR;
goto BAILOUT;
}
currPtr = _ftelli64(m_fileSystemInfo.fp);
}
error = 0;
BAILOUT:
return error;
}
However the above function is taking me to wrong postion.
For example when I want to seek to group number = 2 with m_fileSystemInfo.SizeOfBlockGroup = 2043982
and m_fileSystemInfo.BlockSize = 4096.
I'm expecting currPrt = 2043982*4096*2 = 16744300544 (0x3E609C000), But _ftelli64 is returning (0xE609C000).
Please suggest what could be going wrong. Also please advice what is the best way to deal with large files on windows in c++.
Update::
I found that the seekOffset is getting limited to 8154365952 (0x1e609c000) instead of actual
value of 16744300544 (0x3e609c000) inspite of me using __int64.
So.
_int64 seekOff = (_int64)(grpNum*m_fileSystemInfo.SizeOfBlockGroup*m_fileSystemInfo.BlockSize)
= 2*2043982*4096
is giving 8154365952 instead of 16744300544.
I'm not sure what could the reason as everything is in __int64.
Apparently the problem was with calculation of seek offset. It was generating integer overflow.
Hence I have to convert everything to __int64 even-though I'm working on 64 bits application. I was thinking compiler might be able to do this for me.
__int64 grpNum = 2;
__int64 sizeOfBlockGroup = 2043982;
__int64 blockSize = 4096;
__int64 seekOffSet = grpNum*sizeOfBlockGroup*blockSize;
which works fine with _fseeki64 and __ftelli64.
Your best bet is to use Win32 API directly and not go through the C RunTime.
Use CreateFile to open the file and SetFilePointerEx to seek
The functions you're calling will end up calling these APIs anyway. In Visual studio you have the CRT code so you can step into _fseeki64 and possibly see where it goes wrong.
When running the release executable only (No problems occur when running through visual studio) my program crashes. When using "attach to process" function visual studio indicates the crash occurred in the following function:
World::blockmap World::newBlankBlockmap(int sideLen, int h){
cout << "newBlankBlockmap side: "<<std::to_string((long long)sideLen) << endl;
cout << "newBlankBlockmap height: "<<std::to_string((long long)h) << endl;
short*** bm = new short**[sideLen];
for(int i=0;i<sideLen;i++){
bm[i] = new short*[h];
for(int j=0;j<h;j++){
bm[i][j] = new short[sideLen];
for (int k = 0; k < sideLen ; k++)
{
bm[i][j][k] = blocks->getAIR_BLOCK();
}
}
}
return (blockmap)bm;
}
Which is called from a child class...
World::chunk* World_E::newChunkMap(World::floatmap north, World::floatmap east, World::floatmap south, World::floatmap west
,float lowlow, float highlow, float highhigh, float lowhigh, bool displaceSides){
World::chunk* c = newChunk(World::CHUNK_SIZE+1,World::HEIGHT);
for (int i = 0; i < World::CHUNK_SIZE ; i++)
{
for (int k = 0; k < World::CHUNK_SIZE ; k++)
{
c->bm[i][0][k] = blocks->getDUMMY_BLOCK();
}
}
c->bm[(int)floor((float)(World::CHUNK_SIZE+1)/2.0f)-1][1][(int)floor((float)(World::CHUNK_SIZE+1)/2.0f)-1] = blocks->getSTONE_BLOCK();
c->bm[(int)ceil((float)(World::CHUNK_SIZE+1)/2.0f)-1][1][(int)floor((float)(World::CHUNK_SIZE+1)/2.0f)-1] = blocks->getSTONE_BLOCK();
c->bm[(int)floor((float)(World::CHUNK_SIZE+1)/2.0f)-1][1][(int)ceil((float)(World::CHUNK_SIZE+1)/2.0f)-1] = blocks->getSTONE_BLOCK();
c->bm[(int)ceil((float)(World::CHUNK_SIZE+1)/2.0f)-1][1][(int)ceil((float)(World::CHUNK_SIZE+1)/2.0f)-1] = blocks->getSTONE_BLOCK();
return c;
}
where...
class World {
public: typedef short*** blockmap;
...
The line which VS points at is...
short*** bm = new short**[sideLen];
The "attach to process" function stats the Local variables are...
sideLen = 1911407648
h = 0
which is what i did NOT expect, but the cout outputs 9 and 30 respectively, which was expected.
I am aware that most "crashes in release only" problems are due to uninitialized variables, however, I fail to see that related here.
The only error message I get is...
Windows has triggered a breakpoint in Blocks Project.exe.
This may be due to a corruption of the heap
I am stumped on this problem, what's the error? how can I better debug release executable?
I can post more code if needed, however, bear in mind there is a lot of it.
Thank you in advanced.
"And I don't see World::newBlankBlockmap() called from that second chunk of code. – Michael Burr", I forgot that bit, here you go...
World::chunk* World::newChunk(int side, int height){
cout << "newChunk side: "<<std::to_string((long long)side) << endl;
cout << "newChunk height: "<<std::to_string((long long)height) << endl;
chunk* ch = new chunk();
ch->bm = newBlankBlockmap(side,height);
ch->fm = newBlankFloatmap(side);
return ch;
}
where...
struct chunk {
blockmap bm;
floatmap fm;
};
as defined in the World class
To reiterate what the comments where hinting at: From what you've posted, you're code seems to be badly structured. Triple pointer constructs like short*** are almost impossible to debug and should be avoided at all costs. The heap corruption error message you got suggests that you have a bad memory access somewhere in your code, which is impossible to find automatically with your current setup.
Your only options at this point are to either dig through your entire code manually, until you've found the bug, or start refactoring. The latter might seem like the more time-consuming now, but it won't be if you plan to work with this code in the future.
Consider the following as possible hints for a refactoring:
Don't use plain arrays for storing values. std::vector is just as effective and a lot easier to debug.
Avoid plain new and delete. In modern C++ with the STL containers and smart pointers, plain memory allocation should only happen in very rare exceptional cases.
Always range-check your array access operations. If you worry about performance, use asserts which disappear in release builds, but be sure the checks are there when you need them for debugging.
Modeling three-dimensional arrays in C++ can be tricky, since operator[] only offers support for one-dimensional arrays. A nice compromise is using operator() instead, which can take an arbitrary number of indices.
Avoid C-style casts. They can be very unpredictable. Use the C++ casts static_cast, dynamic_castand reinterpret_cast instead. If you find yourself using reinterpret_cast regularly, you probably have a mistake in your design somewhere.
There is a problem in this line short*** bm = new short**[sideLen];. The memory is allocated for sideLen elements, but the assignment line bm[i][j][k] = blocks->getAIR_BLOCK(); requires an array having size sideLen * sideLen * h. To fix this problem changing of the 1st line to short*** bm = new short**[sideLen * sideLen * h]; is required.