Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
crazypenguin
Mar 9, 2005
nothing witty here, move along
Are you sure optimizations are off? That kind of output is exactly what I'd expect if there's even a bit of dead code elimination, or constant propagation. Then the debugger can sometimes show "statements" being executed that don't exist in the compiled program (and so of course they have no effect.)

Try looking at the assembly?

Adbot
ADBOT LOVES YOU

Dog Jones
Nov 4, 2005

by FactsAreUseless
I tried compiling both programs with intel's c++ compiler, and the debugger now indicates the correct values. So I guess the visual c++ debugger generates incorrect debugging information, while intel's generates correct information?

Dog Jones
Nov 4, 2005

by FactsAreUseless

crazypenguin posted:

Are you sure optimizations are off? That kind of output is exactly what I'd expect if there's even a bit of dead code elimination, or constant propagation. Then the debugger can sometimes show "statements" being executed that don't exist in the compiled program (and so of course they have no effect.)

Try looking at the assembly?

I'm sure they're off.

I'll probably take a look at whats actually being generated eventually, but I think I'm just gonna use intel's compiler for the time being. I'm sorta pressed for time and I've spent a bit too long messing around with this goofy problem already, haha.

evensevenone
May 12, 2001
Glass is a solid.
A better idea would be to not reuse variable names like that, even if you can. Based on this comment "I looked back up through the program", I'm guessing that your function is probably too long to begin with. You should really aim for functions no longer than 25-50 lines or so, and that do one thing and one thing only.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Sure, you could say that, but MSVC's compiler/debugger is also absolutely loving broken.

MrMoo
Sep 14, 2000

Developers, developers, developers.

Little does Balmer know Microsoft only targets programmers, programmers, programmers, and developers are out of luck.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Suspicious Dish posted:

Sure, you could say that, but MSVC's compiler/debugger is also absolutely loving broken.
And yet the debugger still manages to be ridiculously better than all of the other options for C++.

seiken
Feb 7, 2005

hah ha ha
Don't reuse the variable name i because your debugger is broken? I think you wanted the coding horrors thread.

Aside, I kind of think number of branches or loops is a much better heuristic for "is this function too big" than number of lines.

seiken fucked around with this message at 01:45 on Jul 21, 2013

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

seiken posted:

Don't reuse the variable name i because your debugger is broken? I think you wanted the coding horrors thread.

That sounds like a practical approach to me. The tools are lovely, but everything else is shittier, so let's make our lives easier by working around the tool.

Subscribing to some ideology about purity because it's clearly the debugger's fault and not yours and you'll just wait for MSVC2020 to fix the bug is something that flat out ignores reality.

Just change the variable name. It doesn't hurt much.

Dog Jones
Nov 4, 2005

by FactsAreUseless
I mean, I was mostly asking about what was going on with the compiler (or debugger). It goes without saying that changing the variable name avoids the issue.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
Hopefully the debugger can at least manage non-overlapping same named variables?
code:
for (int i=0; i<5; ++i) {
 printf("%d\n",i); //debugger updates value when stopped here?
}
for (int i=4; i>=0; --i) {
 printf("%d\n",i); //debugger also updates value when stopped here?
}
Because I'd be totally on board with "don't reuse variable names with overlapping scope" as a sensible thing, but not reusing 'i' like that, where there should be no confusion and where it becomes a pain in the rear end to use different variable names for a series of quick iterators, would suck.

Edit: not that it wouldn't be nice if they fixed the debugger to conform to spec too, of course.

seiken
Feb 7, 2005

hah ha ha

Suspicious Dish posted:

That sounds like a practical approach to me. The tools are lovely, but everything else is shittier, so let's make our lives easier by working around the tool.

Sorry, I didn't necessarily mean you shouldn't rename the variable to avoid the problem. Just that the fact that doing so seems like a reasonable solution is appropriate for the coding horrors thread.

vvv because the debugger should loving work that's why, it's crazy you have to do weird workarounds

seiken fucked around with this message at 23:17 on Jul 21, 2013

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Seems as reasonable a solution as any. Why?

ctz
Feb 6, 2003

Dog Jones posted:

I tried compiling both programs with intel's c++ compiler, and the debugger now indicates the correct values. So I guess the visual c++ debugger generates incorrect debugging information, while intel's generates correct information?

That, or ICC does different register allocation such that both i values get put in the same register.

(This is assuming that the PE/COFF debugging information for a function/BB is along the lines of 'variable i is stored in register eax'.)

chglcu
May 17, 2007

I'm so bored with the USA.

roomforthetuna posted:

Hopefully the debugger can at least manage non-overlapping same named variables?
code:
for (int i=0; i<5; ++i) {
 printf("%d\n",i); //debugger updates value when stopped here?
}
for (int i=4; i>=0; --i) {
 printf("%d\n",i); //debugger also updates value when stopped here?
}
Because I'd be totally on board with "don't reuse variable names with overlapping scope" as a sensible thing, but not reusing 'i' like that, where there should be no confusion and where it becomes a pain in the rear end to use different variable names for a series of quick iterators, would suck.

Edit: not that it wouldn't be nice if they fixed the debugger to conform to spec too, of course.

Looks like it gives you the correct one when you're inside a loop, at least. Outside of loops, you apparently get the variable from the last executed loop in the current scope. And in the locals tab, you'll have an entry for each loop counter variable even though they're out of scope. So, yeah, it seems like it just wasn't fixed to handle the standard scoping rules when the rest of Visual C++ was. Kinda surprised this hasn't bit me in the rear end before, really.

Dog Jones
Nov 4, 2005

by FactsAreUseless
Do you guys think it would be kosher to use uintptr_t on a coding test even though it is not guaranteed to be defined by the standard library?

For reference:
http://www.cplusplus.com/reference/cstdint/

Hughlander
May 11, 2005

Dog Jones posted:

Do you guys think it would be kosher to use uintptr_t on a coding test even though it is not guaranteed to be defined by the standard library?

For reference:
http://www.cplusplus.com/reference/cstdint/

Yes, if you really feel nervous you could even #error if UINTPTR_MAX isn't defined.

Dren
Jan 5, 2001

Pillbug
Can someone help me out with the kind of things I could look for that might cause the problem I'm seeing?

I am using zopflipng from https://code.google.com/p/zopfli/

For a particular file I have I'm getting a core due to an assert failure but only with certain build flags on certain architectures. I have it compiled for RedHat 4, GCC 3.4.6 20060404 (Red Hat 3.4.6-11), and for RedHat 6, GCC 4.4.6 20120305 (Red Hat 4.4.6-4). On either platform when I compile it 32-bit with no optimization flags, it cores on an assert in deflate.c:272. When I compile it 32 bit w/ -O2 it works fine on both platforms. 64bit works on both platforms, -O2 or no.

I would suspect a memory error but Valgrind reports no memory errors.
code:
==13912== Memcheck, a memory error detector.
==13912== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
==13912== Using LibVEX rev 1575, a library for dynamic binary translation.
==13912== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.
==13912== Using valgrind-3.1.1, a dynamic binary instrumentation framework.
==13912== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
==13912== For more details, rerun with: -v
==13912== 
Optimizing problem.png
zopflipng: src/zopfli/deflate.c:272: AddLZ77Data: Assertion `expected_data_size == 0 || testlength == expected_data_size' failed.
==13912== 
==13912== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 15 from 1)
==13912== malloc/free: in use at exit: 1,145,100 bytes in 32 blocks.
==13912== malloc/free: 327,801 allocs, 327,769 frees, 287,206,224 bytes allocated.
==13912== For counts of detected errors, rerun with: -v
==13912== searching for pointers to 32 not-freed blocks.
==13912== checked 1,255,128 bytes.
==13912== 
==13912== LEAK SUMMARY:
==13912==    definitely lost: 0 bytes in 0 blocks.
==13912==      possibly lost: 320 bytes in 12 blocks.
==13912==    still reachable: 1,144,780 bytes in 20 blocks.
==13912==         suppressed: 0 bytes in 0 blocks.
==13912== Reachable blocks (those to which a pointer was found) are not shown.
==13912== To see them, rerun with: --show-reachable=yes
Aborted (core dumped)
Anyone have any idea what might cause an error like this?

Dren
Jan 5, 2001

Pillbug
It appears that lodepng, used by zopflipng, is stomping on my stack during a call to realloc. So that's nice.

MrMoo
Sep 14, 2000

Dog Jones posted:

Do you guys think it would be kosher to use uintptr_t on a coding test even though it is not guaranteed to be defined by the standard library?

For reference:
http://www.cplusplus.com/reference/cstdint/

I can understand int8_t is not supported on platforms with native 8-bit types, I presume intptr_t doesn't work with suitably perverse pointers. Apparently AS/400 has 16-byte pointers and fit that niche.

MrMoo fucked around with this message at 02:12 on Aug 1, 2013

Dog Jones
Nov 4, 2005

by FactsAreUseless

Hughlander posted:

Yes, if you really feel nervous you could even #error if UINTPTR_MAX isn't defined.

Alright, thanks pal.

Boz0r
Sep 7, 2006
The Rocketship in action.
I'm trying to do some OpenGL tutorials from http://www.arcsynthesis.org/gltut/. I've compiled the GLSDK I need, but when try to build the framework from the first tutorial, I get the following error:

code:
error C2664: 'void (GLDEBUGPROCARB,const void *)' : cannot convert parameter 1 from 'overloaded-function' to 'GLDEBUGPROCARB'
I use Visual C++ Express 2010 on Windows 7 and I just use the project file generated by premake4.exe.

Any ideas?

EDIT:
Also, the tutorial itself gives me these errors:
code:
2>frameworkD.lib(framework.obj) : error LNK2019: unresolved external symbol "bool __cdecl glload::IsVersionGEQ(int,int)" (?IsVersionGEQ@glload@@YA_NHH@Z) referenced in function _main
2>frameworkD.lib(framework.obj) : error LNK2019: unresolved external symbol "int __cdecl glload::LoadFunctions(void)" (?LoadFunctions@glload@@YAHXZ) referenced in function _main
2>.\Tut 01 MainD.exe : fatal error LNK1120: 2 unresolved externals

Boz0r fucked around with this message at 15:43 on Aug 1, 2013

nielsm
Jun 1, 2009



Post your code.

It's complaining about a specific function call having an invalid parameter. So post that function call. And what that parameter is defined as.

Boz0r
Sep 7, 2006
The Rocketship in action.
I've just downloaded the code, I haven't even changed anything yet.

code:
	void APIENTRY DebugFunc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
			   const GLchar* message, GLvoid* userParam)

	...

	if(!glload::IsVersionGEQ(3, 3))
	{
		printf("Your OpenGL version is %i, %i. You must have at least OpenGL 3.3 to run this tutorial.\n",
			glload::GetMajorVersion(), glload::GetMinorVersion());
		glutDestroyWindow(window);
		return 0;
	}

	if(glext_ARB_debug_output)
	{
		glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
		glDebugMessageCallbackARB(DebugFunc, (void*)15);
	}
I think the two other errors are because VS can't find the library files even though I've pointed the linker to the lib folder

EDIT:
I've tried moving over to Linux, but now I get a different set of errors:

code:
Linking Tut 01 Main
/usr/bin/ld: ../glsdk/freeglut/lib/libfreeglutD.a(freeglut_state.o): undefined reference to symbol 'XGetWindowAttributes'
/usr/bin/ld: note: 'XGetWindowAttributes' is defined in DSO /usr/lib/x86_64-linux-gnu/libX11.so.6 so try adding it to the linker command line
/usr/lib/x86_64-linux-gnu/libX11.so.6: could not read symbols: Invalid operation
collect2: error: ld returned 1 exit status
make[1]: *** [Tut 01 MainD] Error 1
make: *** [Tut 01 Main] Error 2

Boz0r fucked around with this message at 14:12 on Aug 2, 2013

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?
C++ code:
class abstractClass { 
	public:
		virtual void foo() = 0;
};
class concreteClass : public abstractClass {
	public: 
		void foo() {}
};

...

abstractClass blah = concreteClass();
gives me the error:
code:
error: cannot allocate an object of abstract type ‘abstractClass’
Is there a way around this, or do I have to use a pointer and new?

That Turkey Story
Mar 30, 2003

HappyHippo posted:

C++ code:
class abstractClass { 
	public:
		virtual void foo() = 0;
};
class concreteClass : public abstractClass {
	public: 
		void foo() {}
};

...

abstractClass blah = concreteClass();
gives me the error:
code:
error: cannot allocate an object of abstract type ‘abstractClass’
Is there a way around this, or do I have to use a pointer and new?

You don't have to use dynamic memory allocation, you can just create an instance of the child on the stack and then make an abstractClass reference to it. If your compiler supports r-value references, the easiest way would be to simply do:

code:
abstractClass&& blah = concreteClass();

raminasi
Jan 25, 2005

a last drink with no ice

That Turkey Story posted:

code:
abstractClass&& blah = concreteClass();

This is making me :psyduck: but I can't figure out why.

nielsm
Jun 1, 2009



GrumpyDoctor posted:

This is making me :psyduck: but I can't figure out why.

Looks like the object is getting stack-allocated as a temporary, then ... what happens? Does "blah" actually have the storage for the object, or is it just kind-of in limbo?

Why would you even ever want to do that thing, having a local non-pointer non-reference variable of with formal type of an abstract class but actual type of a concrete subclass? I can't think of any cases where having the variable be of the concrete class would not work.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

nielsm posted:

Why would you even ever want to do that thing, having a local non-pointer non-reference variable of with formal type of an abstract class but actual type of a concrete subclass? I can't think of any cases where having the variable be of the concrete class would not work.
Not real code, but something where the intent is like
code:
AbstractClass &&x;
switch (param) {
  case 1:
    x=ConcreteClassA();
    break;
  case 2:
    x=ConcreteClassB();
    break;
  default:
    gently caress you;
}
(I don't understand why it was && rather than & in Turkey's version, nor do I know if there's a way to do this on the stack, but it's an example of where you would want the variable itself to be non-concrete!)

Deus Rex
Mar 5, 2005

Why does this not compile:

C++ code:
AbstractClass *blah =  (argc == 1) ? new ConcreteClassA() : new ConcreteClassB();
pre:
foo.cpp|23 col 40 error| incompatible operand types ('ConcreteClassA *' and 'ConcreteClassB *')
when this does?

C++ code:
AbstractClass *blah; 
(argc == 1) ? blah = new ConcreteClassA() : blah = new ConcreteClassB();

That Turkey Story
Mar 30, 2003

nielsm posted:

Looks like the object is getting stack-allocated as a temporary, then ... what happens? Does "blah" actually have the storage for the object, or is it just kind-of in limbo?

roomforthetuna posted:

(I don't understand why it was && rather than & in Turkey's version, nor do I know if there's a way to do this on the stack, but it's an example of where you would want the variable itself to be non-concrete!)

That is on the stack. C++ has a rule that the life of a temporary is extended to match the life of the reference, unless that reference is a non-static datamember. This was true in C++98, as well, but since a temporary cannot be directly used to initialize a reference to non-const, you couldn't directly take advantage of this for mutable objects (this is why you need && instead of &). Now that we have r-value references, you can use this feature with references to non-const objects.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Deus Rex posted:

Why does this not compile:
when this does?
The ternary operator has to have one type for its 'return value'; the compiler can't infer the common-ground of a shared base class. If it was a function you'd give the base class as the return value in the declaration, but since the ternary operator has no declaration, it has to infer the return type, and it can't.

You could do
code:
AbstractClass *blah =  (argc == 1) ? (AbstractClass *)new ConcreteClassA() : (AbstractClass *)new ConcreteClassB();
(Or whatever is the appropriate long-winded new [probably 10 years old] C++ casting method.)

roomforthetuna fucked around with this message at 01:43 on Aug 3, 2013

Rottbott
Jul 27, 2006
DMC
I wouldn't use a ternary here at all, for what is by now an obvious reason. If I were made to, the 'appropriate long-winded' C++ cast would be static_cast<>, but I would instead use a function-style cast here.

I generally use function-style cast wherever static_cast<> seems over the top; I don't like using C-style casts in case I miss a const or something, but for simple types it seems ok. It's usually cleaner anyway due to fewer brackets (though not in this example). It's great for looping through enum values.

Rottbott fucked around with this message at 12:27 on Aug 3, 2013

King
Jun 28, 2006
Not Kong
I'm just starting out with c++, so I'm playing around with implementing bubble sorts. Both of these functions work perfectly fine, but I'm just curious as to whether either of these implementations would be considered better than the other. The question boils down to whether a for or while loop is more "useful" I suppose; it seems to me that while is better since a new int doesn't have to be declared each time (not that that would be a huge bottleneck, but it seems like a slight improvement to me). Any opinions?

code:
void BubbleSort(int * array, int element) {
	int i, temp;
	i = temp = 0;
	bool swapped = true;

	while(swapped) {
		swapped = false;
		i++;
		for(int j = 0; j < element - i; j++) {
			if(array[j] > array[j + 1]) {
				temp = array[j];
				array[j] = array[j + 1];
				array[j + 1] = temp;
				swapped = true;
			}
		}
	}
}

void BubbleSort(int * array, int element) {
	int i, j, temp;
	i = j = temp = 0;
	bool swapped = true;

	while(swapped) {
		swapped = false;
		i++;
		j = 0;
		while(j < element - i) {
			if(array[j] > array[j + 1]) {
				temp = array[j];
				array[j] = array[j + 1];
				array[j + 1] = temp;
				swapped = true;
			}
			j++;
		}
	}
}

nielsm
Jun 1, 2009



It's better to use the "for" loop because for-loops are intended for looping over known-length data, and your list has a known length.

Also, consider that after one iteration the final element in the array is guaranteed to be the largest of them all, meaning you know that after "i" iterations, the last "i" elements are in correct order.
This can slightly improve the running time of the algorithm (that will stay O(n*n)), though it doesn't change its asymptotic complexity, but more importantly it puts an upper bound on the number of iterations for the outer loop. That will allow you to avoid the "while" loop condition on a flag.

King
Jun 28, 2006
Not Kong
Great, thanks. I'm also working on a practice dynamic array class which stores an array of integers that can be "dynamically" reallocated. I'm having errors with the destructor, though. Simplified, I have this:

code:
class DynamicArray {
private:
  int capacity, size;
  int * array;
public:
DynamicArray () {
  capacity = 10;
  size = 0;
  array = new int[capacity];
}
~DynamicArray() { delete[] array };
}
This works fine, but I also added an Append function which adds an integer to the array.
code:
void DynamicArray::Append(int n) {
  if(size == capacity) {
    int * temp = new int[size + 10];

    for(int i = 0; i < size; i++)
      temp[i] = array[i];
		
    delete[] array;
    array = new int[size + 10];
		
    for(int i = 0; i < size; i++)
      array[i] = temp[i];
		
  delete[] temp;
  capacity += 10;
  }
  array[size] = n;
  size++;
}
This function also works perfectly, but the program breaks with an exception when the destructor is called. What issue am I having?

Rottbott
Jul 27, 2006
DMC
At first glance I see a couple of things wrong:

- Is this the exact code you used? It doesn't compile due to a misplaced semi-colon in the destructor.
- You unnecessarily do two allocations when growing, rather than just reassigning 'array' to point at 'temp'.
- It's not exception safe. I've never actually used C++ exceptions but it looks pretty dodgy from that perspective.
- Repeating the '+ 10' everywhere is just asking for trouble, use a constant.

However I can't actually see what's causing your exception, and I don't get one when running it here. Post more details or your complete code or wait for someone smarter than me. :)

nielsm
Jun 1, 2009



Yeah, please either post the code you are actually using, a minimal example that still shows the same behaviour, or just don't post at all.

But the code is poorly structured, as Rottbott points out. You should at the very least have a "resize" function on the class that re-allocates the back storage. If you write it such that it can also handle the back-storage being null (just making an initial allocation) or the new size being zero (delete and null the storage) you can have that handle the meat of the construction and destruction as well.
There's a ton of other things you should be doing as well to follow good C++ style, but at least start with this.

King
Jun 28, 2006
Not Kong
Yeah, I just started working on it for fun/practice and I know tons of little things I should do and there's tons of little/big things I don't know how to do. The problem arises if I use that class code (with proper semicolon, I just typed up a quick version of it) with this simple demonstration:

edit: here's everything exactly as i have it.

EDIT2: Figured it out! The error is with my calling of new int in the constructor, I set it to the wrong size. Feel free to point out anything especially horrible with the rest of the code.


code:

class IntArray {
private:
	int capacity;
	int size;
	int * array;
	static const int expandSize = 10;

public:
	IntArray();
	IntArray(int cap);
	IntArray(int * arr, int cap);

	int Value(int n);
	int Capacity();
	int Size();

	void Resize(int cap);
	void Append(int n);

	~IntArray() {
		delete[] array;
	}
};

IntArray::IntArray() {
	capacity = 10;
	size = 0;
	array = new int[capacity];
}

IntArray::IntArray(int cap) {
	capacity = cap;
	size = 0;
	array = new int[capacity];
}

IntArray::IntArray(int * arr, int elements) {
	capacity = elements * 2;
	size = elements;
	array = new int[elements];

	for(int i = 0; i < elements; i++)
		array[i] = arr[i];
}

int IntArray::Value(int n) {
	return array[n];
}

int IntArray::Capacity() {
	return capacity;
}

int IntArray::Size() {
	return size;
}

void IntArray::Resize(int cap) {
	int * temp = new int[cap];

	for(int i = 0; i < size; i++)
		temp[i] = array[i];
	
	delete[] array;
	array = new int[cap];
	
	for(int i = 0; i < size; i++)
		array[i] = temp[i];

	delete[] temp;
	capacity = cap;
}

void IntArray::Append(int n) {
	if(size == capacity) {
		Resize(capacity + expandSize);
	}

	array[size] = n;
	size++;
}

int main() {
	int a[10] = {4, 41, 5, 52, 0, 56, 99, 42, 411, 8};
	IntArray arr(a, 10);
	
	for(int i = 0; i < arr.Size(); i++) {
		cout << i + 1 << ":\t" << arr.Value(i) << endl;
	}

	cout << "Size: " << arr.Size() << ", Capacity: " << arr.Capacity() << endl;
	cout << "Appending 59, 141, 6..." << endl;
	
	arr.Append(59);
	arr.Append(141);
	arr.Append(6);

	for(int i = 0; i < arr.Size(); i++) {
		cout << i + 1 << ":\t" << arr.Value(i) << endl;
	}

	cout << "Size: " << arr.Size() << ", Capacity: " << arr.Capacity() << endl;

	cin.get();
	cin.get();
	return 0;
}
Where Value() returns the value at i. Everything works perfectly up to the cin.get()s (which are there to keep the console from closing.) However, when main returns and the destructor is called, I get the breakpoint (using visual studio express 2012):
code:
HEAP[DynamicArray.exe]: Heap block at 011E9EE8 modified at 011E9F3C past requested size of 4c
DynamicArray.exe has triggered a breakpoint.
And it guides me to this function from dbgheap.c.

King fucked around with this message at 19:32 on Aug 3, 2013

Adbot
ADBOT LOVES YOU

stochastastic
Jun 5, 2003

King posted:

Yeah, I just started working on it for fun/practice and I know tons of little things I should do and there's tons of little/big things I don't know how to do. The problem arises if I use that class code (with proper semicolon, I just typed up a quick version of it) with this simple demonstration:

*snip*

Where Value() returns the value at i. Everything works perfectly up to the cin.get()s (which are there to keep the console from closing.) However, when main returns and the destructor is called, I get the breakpoint (using visual studio express 2012):
code:
HEAP[DynamicArray.exe]: Heap block at 011E9EE8 modified at 011E9F3C past requested size of 4c
DynamicArray.exe has triggered a breakpoint.
And it guides me to this function from dbgheap.c.



If you read the error message "Heap block at 011E9EE8 modified at 011E9F3C past requested size of 4c" or google "Heap block at modified at past requested size of" you should realize that what's going on is that you are modifying a value past the length of your array. So, you should look for spots in your code where you are allocating the space for your array and where you are writing to the array. Here's your problem:

code:
IntArray::IntArray(int * arr, int elements) {
	capacity = elements * 2;
	size = elements;
	array = new int[elements];

	for(int i = 0; i < elements; i++)
		array[i] = arr[i];
}
Do you see something wrong with the that allocation when matched with this code:
code:
void IntArray::Append(int n) {
	if(size == capacity) {
		Resize(capacity + expandSize);
	}

	array[size] = n;
	size++;
}
specifically the part where you write
code:
array[size] = n;

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply