Allocating on the stack

This is a pretty beginner question but I'm quite sure I'm right and I am quite clearly wrong, so I feel the need to ask: what happens when you dynamically allocate memory on the stack? It stays there after the variable has left the function's scope, right?

Here's the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Image* imgCreate(int w, int h, int dcs)
{
   Image* image = (Image*) malloc (sizeof(Image)); //RELEVANT
   assert(image);
   image->width  = w;
   image->height = h;
   image->dcs = dcs;
   image->buf = malloc (w * h * dcs * sizeof(float));
   assert(image->buf);
   return image;
}
Image* imgCopy(Image* image)
{
   int w = imgGetWidth(image);
   int h = imgGetHeight(image);
   int dcs = imgGetDimColorSpace(image);
   Image* img1=imgCreate(w,h,dcs); //RELEVANT
   int x,y;
   float rgb[3];

   for (y=0;y<h;y++){
      for (x=0;x<w;x++) {
         imgGetPixel3fv(image,x,y,rgb);
         imgSetPixel3fv(img1,x,y,rgb);
      }
   }

   return img1;
}
void imgMedian(Image* img) 
{
	int x,y,dcs=img->dcs,z=img->width*dcs;
	Image* copy = imgCreate(img->width,img->height,img->dcs); //RELEVANT
	float* img_buf = img->buf;
	copy->dcs=dcs;
	copy->height=img->height;
	copy->width=img->width;
	for(x=0;x<img->dcs*img->width;x++)
		copy->buf[x]=img_buf[x];
	for(y=1;y<img->height-1;y++)
	{
		copy->buf[y*z]=img_buf[y*z];
		for(x=1;x<img->dcs*(img->width-1);x++)
		{
			copy->buf[x+y*z]=(img_buf[x-dcs+(y+1)*z]+img_buf[x+dcs+(y+1)*z]+img_buf[x-dcs+(y-1)*z]+img_buf[x+dcs+(y-1)*z]+
							img_buf[x-dcs+y*z]+img_buf[x+dcs+y*z]+img_buf[x+(y-1)*z]+img_buf[x+(y+1)*z]+img_buf[x+y*z])/9;
		}
		copy->buf[y*z+x]=img_buf[y*z+x];
		copy->buf[y*z+x]=img_buf[y*z+x+1];
		copy->buf[y*z+x]=img_buf[y*z+x+2];

	}
	for(x=0;x<img->dcs*img->width;x++)
		copy->buf[x+y*z]=img->buf[x+y*z];
	imgDestroy(img);
	img=copy;  //RELEVANT
	//img=imgCopy(copy); //RELEVANT
}


Those are just the relevant functions, of course. Really, all that matters is that copy (in imgMedian()) is created through imgCreate(), which dynamically allocates it's memory slot, and img then loses it's own object and instead points to copy's memory slot.

However, should I then manipulate img after calling imgMedian(), all the information within it has been lost.

However, should I, instead of doing img=copy use img=imgCopy(copy);, everything works fine.

I feel like I'm making a really stupid mistake here.
Last edited on
wasabi wrote:
It stays there after the variable has left the function's scope, right?

Yes.

In your case (malloc) the memory is allocated on the heap. So, you should use free somewhere to deallocate that memory.

http://www.cplusplus.com/reference/clibrary/cstdlib/free/

However, it's not necessary to use dynamic memory allocation here. You can just build a temporary Image object inside your imgCreate function and then return an Image instead of an Image pointer. Same for your imgCopy function.
Last edited on
Oh yeah, sure. There's an imgDestroy() function that deals with allocated memory.

However, that didn't answer my question.

For whatever reason, using imgMedian() doesn't work. When the function "returns", the information held on the img pointer (which should point to copy's information) is lost. If I use the debugger, the function "returns" and the values of img's members are all junk.

However, should I replace imgMedian()'s last line of code (img=copy;) for img=imgCopy(copy);, it works.
Last edited on
Ah, try changing the signature to this -> void imgMedian(Image * & img)
Gives me a syntax error.

error C2143: syntax error : missing ')' before '&'
error C2143: syntax error : missing '{' before '&'
error C2059: syntax error : '&'
error C2059: syntax error : ')'


Could this be due to the fact that this is actually a C code, not C++?

EDIT: Nevermind. I changed the code to .cpp and those errors disappeared. Just needed to modify the .h accordingly and now it works fine. Many thanks.

I'd seen that '&' in the declarations before, but never knew what it did. I still don't, really. What does it do?
Last edited on
Mmmm... Yes, you can't use references in C. The thing is that you pass your img pointer by value, which means that anything you do to modify the pointer itself (and not the data pointed to by it) doesn't affect the pointer you pass. I'm surprised that you say that this -> img=imgCopy(copy); works. It shouldn't, for the same reason. A workaround would be to pass an Image* pointer, that is an argument of type Image**. Another solution would be to make your function take no arguments and return an Image pointer instead.
I think you missed my EDIT. :p

"Nevermind. I changed the code to .cpp and those errors disappeared. Just needed to modify the .h accordingly and now it works fine. Many thanks.

I'd seen that '&' in the declarations before, but never knew what it did. I still don't, really. What does it do?"
wasabi wrote:
I think you missed my EDIT. :p

Yes, I did...

Could I see the new code (if you don't mind)? How did you fix it?

EDIT: Info on the '&' symbol -> http://cplusplus.com/doc/tutorial/functions2/

EDIT 2: Note that if you used the void imgMedian(Image * & img) thing, it won't compile on a C compiler.
Last edited on
I changed absolutely nothing.

Just the filename from image.c to image.cpp and the declaration (in the .h) and definition-header in the now-.cpp

.h
1
2
//void imgMedian(Image * img); became
void imgMedian(Image * & img);


.cpp
1
2
3
4
5
6
7
8
9
/*void imgMedian(Image * img)
{
//code
} //became */

void imgMedian(Image * & img)
{
//code
}


//code being the exact same code I have in the OP.
Last edited on
Okay, but mind that this is not C code, check my second edit above. C doesn't have references. You should do it another way (see the ones I mentioned above) if you want this to also compile on a C compiler.
That's not a problem. We only use C++ compilers, so I don't know why we try to stick to .c ...

But thanks for the info.
Wait, another question. Just looked at the link you sent, and the ampersand they mention is simply a reference, which I'm quite comfortable with. However, as far as I know, since the argument is a pointer, one can by default change its values at will and it will carry on past the function's scope. Right?

Woah, just saw that.

Is this just my old-school C knowledge getting in the way or aren't arguments passed by reference supposed to be declared as function(int* a);?

What's the difference between int* a and int& a? Aren't both the memory address for a?
Last edited on
m4ster r0shi wrote:
The thing is that you pass your img pointer by value, which means that anything you do to modify the pointer itself (and not the data pointed to by it) doesn't affect the pointer you pass.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
using namespace std;

void f1v(int * pvi) {(*pvi)++;}

void f1r(int * & pri) {(*pri)++;}

void f2v(int * pvi) {pvi=0;}

void f2r(int * & pri) {pri=0;}

int main()
{
    int a=10;
    int * pa=&a;

    f1v(pa);
    cout << a << endl;

    f1v(pa);
    cout << a << endl;

    f2v(pa);
    cout << pa << endl;

    f2r(pa);
    cout << pa << endl;

    cout << "\nhit enter to quit...";
    cin.get();
    return 0;
}

EDIT: Your problem was that you wanted to modify the pointer itself.
Passing the pointer by reference ( '* &' syntax) solved the problem.
Last edited on
AHA!

Yeah, reading that in bold solved it for me. A pointer as an argument allows you to change the value of the pointed object, but not the value of the pointer itself.

Gotcha.

Many thanks. Again.
Topic archived. No new replies allowed.