I've looked many places without finding enough information to help me solve my issue. Basically, I want a three dimensional array of 16*16*256 instances of a class. This caused a stack overflow, so I attempted a vector but that also crashed. Finally, I am attempting to allocate heap memory via triple, double, and single pointers.
/* Values chunkX, chunkY, chunkZ used below are static constant integers*/
Block*** blocks;
blocks = new Block**[chunkX];
for (int i = 0; i < chunkX; i++) {//Initialize all arrays
blocks[i] = new Block*[chunkZ];
for (int u = 0; u < chunkZ; u++) {
blocks[i][u] = new Block[chunkY];
}
}
This made sense to me but probably is incorrect. The C2040 error is at the line where blocks is first defined.
Later in the code, I attempt:
Block& block = blocks[x][z][y];
But it tells me C2530 'block': references must be initialized ... even though I initialized them above..? And then it just stops compiling because of these two errors. I'm quite confused and couldn't find any triple pointer tutorials using new. I don't think the amount of memory I want is unreasonable, because the Block class isn't huge.
EDIT (SOLVED):
Apparently this was not a code problem but just the compiler bugging out. It compiles now without changes made. Thanks for the comments and sorry for the inconvenience.
Related
I'm dealing with someone else's code as a part of my assignment and have ran into trouble. Instead of running smoothly, the given code throws out the mentioned error in the following function:
template <typename T>
inline T ***Create3DArray(int d1, int d2, int d3) {
T ***retval;
retval = (T***)malloc((sizeof(T**)+(sizeof(T*)+sizeof(T)*d3)*d2)*d1);
T **ptr = (T**)(retval+d1);
T *ptr2 = (T*)(ptr+d1*d2);
for(int i = 0; i < d1; i++, ptr += d2) {
retval[i] = ptr; // this line triggers the CXX0030 error
for(int j = 0; j < d2; j++, ptr2 += d3) {
retval[i][j] = ptr2;
if(j == 0) {
for(int k = 0; k < d3; k++)
retval[i][j][k] = 0;
} else
memcpy(retval[i][j], retval[i][0], sizeof(T)*d3);
}
}
return retval;
}
Any clues as to why this happens? I doubt that someone would publish their code if it couldn't even be ran. Is this maybe a Visual Studio specific issue?
Edit:
I stress the fact that I'm not the one who has written the code, and have very little insight regarding the big picture (although the problem seems localized). Here's some more info, the line which calls the function Create3DArray is:
float ***pts = Create3DArray<float>(classes->NumParts(), numObjects*m, part_width*part_width);
The arguments are 15, 11988 and 3136, meaning that over 1GB of memory gets allocated.
The link to the project's website is here. The file which I'm currently trying to use can be found under Examples->import_birds200.cpp. Do note that the whole thing is pretty big and uses some 1GB of data.
1.You use of c functions that do not ensure c++ object lifecycle / semantics:
You use malloc() in c++. This is not a great practice, because malloc() doesn't initialize the objects in the allocated area. When you later assign an object, like in retval[i][j][k] = 0; your compiler assumes that retval[i][j][k] already contains an object which is in a stable state.
THis isn't the direct cause of your error. But from the second iteration onwards, depending on how T operator= is implemented, you could have corrupted memory.
If you want to proceed with malloc(), you have to use placement new to initialize the objects properly: new (&retval[i][j][k])T(); // placement creation
You later use memcpy(). This will performe a byte clone of your object, without ensuring the semantic of a copy. For example, if your type T would have member pointing to a memory region allocated during its construction, both the clone and the original would then point to the same region. The first who gets deleted will free the memory. The second will attempt to free again : memory issues guaranteed !
Prefer std::copy() over memcpy(). But this requires an existing object to first be constructed. So in your context, no way arround a placement new : get rid of the special case using the mmemcpy().
2. Memory allocation issues:
It may sound trivial, but allocation could fail. So it would be preferable to put an assert to verify that you didn't get a NULL in return !
I'm suggesting this because that's one of the probable cause of Cxx0030
I have a struct:
typedef struct{
int *issueTypeCount;
}issueTypeTracker;
I've declared a variable of type issueTypeTracker:
issueTypeTracker *typeTracker;
I've allocated necessary memory:
typeTracker = (issueTypeTracker*) malloc(sizeof(issueTypeTracker) * issueTypeList.count());
typeTracker->issueTypeCount = (int*) calloc(65536,sizeof(int));
And then when I try to do something with it, I get a segmentation fault
while(qry.next()){ //while there are records in the query
for(j=0;j<locationList.count();j++){ // no problem
if(qry.value(1) == locationList[j]){ //no problem
for(i=0;i<issueTypeList.count();i++){ //no problem
typeTracker[j].issueTypeCount[i]++; //seg fault as soon as we hit this line
}
}
}
}
I figured it would be a problem with the way i've allocated memory, but as far as I'm aware i've done it correctly. I've tried the solutions proposed in this question, however it still did not work.
I've tried replacing typeTracker->issueTypeCount = (int*) calloc(65536,sizeof(int)); with:
for(j=0;j<issueTypeList.count();j++){
typeTracker[j].issueTypeCount = (int*) calloc(65536,sizeof(int));
}
But I still get the same issue. This happens with any value of j or i, even zero.
This is a lot more trouble than it's worth and a poor implementation of what I'm trying to do anyway, so I'm probably going to scrap this entire thing and just use a multidimensional array. Even so, I'd like to know why this doesn't work, so in the future I don't have trouble when i'm faced with a similar scenario.
You have several issues. Firstly, you're not checking your allocations for success, so any of your pointers could be NULL/nullptr.
Secondly,
typeTracker->issueTypeCount = (int*) calloc(65536,sizeof(int));
is equivalent to
typeTracker[0].issueTypeCount = (int*) calloc(65536,sizeof(int));
so, you initialized the issueTypeCount member for only the first issueTypeTracker in your array. For the other issueTypeList.count() - 1 elements in the array, the pointer is uninitialized.
Therefore this line:
typeTracker[j].issueTypeCount[i]++; //seg fault as soon as we hit this line
will invoke UB for any j>0. Obviously if your allocation failed, you have UB for j==0 as well.
Note: i'm using the c++ compiler, hence why I can use pass by reference
i have a strange problem, and I don't really know what's going on.
Basically, I have a text file: http://pastebin.com/mCp6K3HB
and I'm reading the contents of the text file in to an array of atoms:
typedef struct{
char * name;
char * symbol;
int atomic_number;
double atomic_weight;
int electrons;
int neutrons;
int protons;
} atom;
this is my type definition of atom.
void set_up_temp(atom (&element_record)[DIM1])
{
char temp_array[826][20];
char temp2[128][20];
int i=0;
int j=0;
int ctr=0;
FILE *f=fopen("atoms.txt","r");
for (i = 0; f && !feof(f) && i < 827; i++ )
{
fgets(temp_array[i],sizeof(temp_array[0]),f);
}
for (j = 0; j < 128; j++)
{
element_record[j].name = temp_array[ctr];
element_record[j].symbol = temp_array[ctr+1];
element_record[j].atomic_number = atol(temp_array[ctr+2]);
element_record[j].atomic_weight = atol(temp_array[ctr+3]);
element_record[j].electrons = atol(temp_array[ctr+4]);
element_record[j].neutrons = atol(temp_array[ctr+5]);
element_record[j].protons = atol(temp_array[ctr+6]);
ctr = ctr + 7;
}
//Close the file to free up memory and prevent leaks
fclose(f);
} //AT THIS POINT THE DATA IS FINE
Here is the function I'm using to read the data. When i debug this function, and let it run right up to the end, I use the debugger to check it's contents, and the array has 100% correct data, that is, all elements are what they should be relative to the text file.
http://i.imgur.com/SEq9w7Q.png This image shows what I'm talking about. On the left, all the elements, 0, up to 127, are perfect.
Then, I go down to the function I'm calling it from.
atom myAtoms[118];
set_up_temp(myAtoms); //AT THIS POINT DATA IS FINE
region current_button_pressed; // NOW IT'S BROKEN
load_font_named("arial", "cour.ttf", 20);
panel p1 = load_panel("atomicpanel.txt");
panel p2 = load_panel("NumberPanel.txt");
As soon as ANYTHING is called, after i call set_up_temp, the elements 103 to 127 of my array turn in to jibberish. As more things get called, EVEN MORE of the array turns to jibberish. This is weird, I don't know what's happening... Does anyone have any idea? Thanks.
for (j = 0; j < 128; j++)
{
element_record[j].name = temp_array[ctr];
You are storing, and then returning, pointers into temp_array, which is on the stack. The moment you return from the function, all of temp_array becomes invalid -- it's undefined behavior to dereference any of those pointers after that point. "Undefined behavior" includes the possibility that you can still read elements 0 through 102 with no trouble, but 103 through 127 turn to gibberish, as you say. You need to allocate space for these strings that will live as long as the atom object. Since as you say you are using C++, the easiest fix is to change both char * members to std::string. (If you don't want to use std::string, the second easiest fix is to use strdup, but then you have to free that memory explicitly.)
This may not be the only bug in this code, but it's probably the one causing your immediate problem.
In case you're curious, the reason the high end of the data is getting corrupted is that on most (but not all) computers, including the one you're using, the stack grows downward, i.e. from high addresses to low. Arrays, however, always index from low addresses to high. So the high end of the memory area that used to be temp_array is the part that's closest to the stack pointer in the caller, and thus most likely to be overwritten by subsequent function calls.
Casual inspection yields this:
char temp_array[826][20];
...
for (i = 0; f && !feof(f) && i < 827; i++ )
Your code potentially allows i to become 826. Which means you're accessing the 827th element of temp_array. Which is one past the end. Oops.
Additionally, you are allocating an array of 118 atoms (atom myAtoms[118];) but you are setting 128 of them inside of set_up_temp in the for (j = 0; j < 128; j++) loop.
The moral of this story: Mind your indices and since you use C++ leverage things like std::vector and std::string and avoid playing with arrays directly.
Update
As Zack pointed out, you're returning pointers to stack-allocated variables which will go away when the set_up_temp function returns. Additionally, the fgets you use doesn't do what you think it does and it's HORRIBLE code to begin with. Please read the documentation for fgets and ask yourself what your code does.
You are allocating an array with space for 118 elements but the code sets 128 of them, thus overwriting whatever happens to live right after the array.
Also as other noted you're storing in the array pointers to data that is temporary to the function (a no-no).
My suggestion is to start by reading a good book about C++ before programming because otherwise you're making your life harder for no reason. C++ is not a language in which you can hope to make serious progress by experimentation.
I'm using a bit of legacy type code that runs on a framework, so I can't really explain whats going on at a lower level as I don't know.
However my code creates an array of objectives.
int maxSize = 20;
myObjects = new Object*[maxSize+1];
myObjects[0] = new item1(this);
myObjects[1] = new item2(this);
for(int i=2; i != maxSize+1; i++){
myObjects[i] = new item3(this);
}
myObjects[maxSize+1] = NULL;
If maxSize is larger than 30 I get a whole load of errors I've never seen. Visual Studio draws up an error in xutility highlighting:
const _Container_base12 *_Getcont() const
{ // get owning container
return (_Myproxy == 0 ? 0 : _Myproxy->_Mycont);
}
I've never used Malloc before, but is this where the problem lies. Should I be assigning using it to avoid this problem?
The absolute value of maxSize is probably not a culprit: allocating 30 pointers should go without trouble on any computer, including most micro-controllers. Using malloc is not going to change anything: you are doing your allocation the way you're supposed to do it in C++.
Here is the likely source of your error:
myObjects[maxSize+1] = NULL;
You have allocated storage for maxSize+1 items, so the valid indexes are between 0 and maxSize. Writing one past the last element is undefined behavior, meaning that a crash could happen. You got lucky with 20 elements, but 30 smoked out this bug for you. Using valgrind utility is a good way to catch memory errors that could cause crashes, even if they currently don't cause them.
int maxSize = 20;
myObjects = new Object*[maxSize+1];
myObjects[0] = new item1(this);
myObjects[1] = new item2(this);
// if maxsize is 1, this loop could be trouble
for(int i=2; i != maxSize; i++){
myObjects[i] = new item3(this);
}
myObjects[maxSize] = NULL;
You're going past the bounds with:
myObjects[maxSize+1] = NULL;
In your example, you created an array with 21 items. That will run from 0..20 but you're trying to write to the 21st element here.
The problem is not with new / delete as far as I can see, and I can't see any reason for switching to malloc here.
You should not use malloc() in C++; you should use new.
There's one possible exception to this: if you have to allocate a block of memory which you intend to pass as an argument to a function which is going to eventually free it using free(). If you used new to allocate such a block the free() would likely cause heap corruption. But this is purely hypothetical -- I've never seen such an API!
I think you can't access offset "maxSize+1". The solution is like:
myObjects = new Object*[maxSize+2];
...
myObjects[maxSize+1] = NULL;
I apologise for posting a question that has been asked many times (I've just read 10 pages of them) but I can't find a solution.
I'm working on a multi-threaded graphic/audio program using OpenGL and Portaudio respectively. The audio thread uses a library I'm making for audio processing objects. The SIGSEGV happens maybe 20% of the time (much less when debugging) and happens when resetting loads of audio objects with new stream information (sample rate, vector size etc). Code::blocks Debugger states the fault as originating from different places each time the fault happens.
This is the audio processing loop:
while(true){
stream->tick();
menuAudio.tick();
{
boost::mutex::scoped_lock lock(*mutex);
if(channel->AuSwitch.resetAudio){
uStreamInfo newStream(channel->AuSwitch.newSrate,
channel->AuSwitch.newVSize, channel->AuSwitch.newChans);
menuAudio.resetStream(&newStream);
(*stream) = newStream;
menuAudio.resetStream(stream);
channel->AuSwitch.resetAudio = false;
}
}
}
It checks information from the graphics thread telling it to reset the audio and runs the resetStream function of the patch object, which is basically a vector for audio objects and runs each of them:
void uPatch::resetStream(uStreamInfo* newStream)
{
for(unsigned i = 0; i < numObjects; ++i){
/*This is where it reports this error: Program received signal SIGSEGV,
Segmentation fault. Variables: i = 38, numObjects = 43 */
objects[i]->resetStream(newStream);
}
}
Sometimes it states the SIGSEGV as originating from different locations, but due to the rarity of it faulting when run with the debugger this is the only one I could get to happen.
As there are so many objects, I won't post all of their reset code, but as an example:
void uSamplerBuffer::resetStream(uStreamInfo* newStream)
{
audio.set(newStream, false);
control.set(newStream, true);
stream = newStream;
incr = (double)buffer->sampleRate / (double)stream->sampleRate;
index = 0;
}
Where the audio.set code is:
void uVector::set(uStreamInfo* newStream, bool controlVector)
{
if(vector != NULL){
for(unsigned i = 0; i < stream->channels; ++i)
delete[] vector[i];
delete vector;
}
if(controlVector)
channels = 1;
else
channels = newStream->channels;
vector = new float*[channels];
for(unsigned i = 0; i < channels; ++i)
vector[i] = new float[newStream->vectorSize];
stream = newStream;
this->flush();
}
My best guess would be that it's a stack overflow issue, as it only really happens with a large number of objects, and they each run fine individually. That said, the audio stream itself runs fine and is run in a similar way. Also the loop of objects[i]->resetStream(newStream); should pop the stack after each member function, so I can't see why it would SIGSEGV.
Any observations/recommendations?
EDIT:
It was an incorrectly deleted memory issue. Application Verifier made it fault at the point of the error instead of the occasional faults identified as stemming from other locations. The problem was in the uVector stream setting function, as the intention of the class is for audio vectors using multidimensional arrays using stream->channels, with the option of using single dimensional arrays for control signals. When deleting to reallocate the memory I accidentally set all uVectors regardless of type to delete using stream-> channels.
if(vector != NULL){
for(unsigned i = 0; i < stream->channels; ++i)
delete[] vector[i];
delete vector;
}
Where it should have been:
if(vector != NULL){
for(unsigned i = 0; i < this->channels; ++i)
delete[] vector[i];
delete vector;
}
So it was deleting memory it shouldn't have access to, which corrupted the heap. I'm amazed the segfault didn't happen more regularly though, as that seems like a serious issue.
I you can spare the memory, you can try a tool like Electric Fence (or DUMA, its child) to see if it's an out of bound write that you perform.
Usually these types of segfaults (non-permanent, only occurring sometimes) are relics of a previous buffer overflow somewhere.
You could try Valgrind also, which will have the same effect as the 2 tools above, to the cost of a slower execution.
Also, try to check what's the value of the bad address you're accessing when this happens: is it looking valid? Sometimes a value can be very informative on the bug you're encountering (typically: trying to access memory at 0x12 where 0X12 is the counter in a loop :)).
For stack overflows... I'd suggest trying to increase the stack size of the incriminated thread, see if the bug is reproduced. If not after a good bunch of tries, you've found the problem.
As for windows:
How to debug heap corruption errors?
Heap corruption under Win32; how to locate?
https://stackoverflow.com/search?q=windows+memory+corruption&submit=search
I think you just made it a Stack Overflow issue. :)
In all seriousness, bugs like these are usually the result of accessing objects at memory locations where they no longer exist. In your first code block, I see you creating newStream on the stack, with a scope limited to the if statement it is a part of. You then copy it to a dereferenced pointer (*stream). Is safe and correct assignment defined for the uStreamInfo class? If not explicitly defined, the compiler will quietly provide memberwise copy for object assignment, which is OK for simple primitives like int and double, but not necessarily for dynamically allocated objects. *stream might be left with a pointer to memory allocated by newStream, but has since been deallocated when newStream went out of scope. Now the data at that RAM is still there, and for a moment will look correct, but being deallocated memory, it could get corrupted at any time, like just before a crash. :)
I recommend paying close attention to when objects are allocated and deallocated, and which objects own which other ones. You can also take a divide an conquer approach, commenting out most of the code and gradually enabling more until you see crashes starting to occur again. The bug is likely in the most recently re-enabled code.