Sign in to follow this  

From C# to C++ concept questions..

This topic is 1454 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

 

I Know my way around the C# language fairly well and am looking to try and 'break into' doing some c++ but have a few conceptual questions to ask.

 

My main questions are about pointers and memory management, I believe i have researched and understood what pointers are, and how to use and manipulate them but i do not clearly understand why to use them.

 

C# Example:

 

class Program
    {
        static void Main(string[] args)
        {
            List<int> numberArray = new List<int>();
            Random rnd = new Random();
 
            for (int i = 0; i < 10000000; i++)
            {
                numberArray.Add(rnd.Next());
            }
        }
    }
 
Now, this code should fill a dynamic array allocating memory as needed but when the variable goes out of scope it should be sent to the GC and eventually destroyed correct? 
 
Now, if the same program were to be written in c++ using 'identical code' (ie not pointers) then that array would fill up the stack and the program should crash right?
 
That's why you need pointers? to send large or persistent data to the heap and not overload the stack?
Edited by Mellkor

Share this post


Link to post
Share on other sites

In case we would use identical code, it would mean STL would do all the memory work; you would never get in touch.
By the way a list is something different than an array.

But internal of the STL lib, the lib use a pointer to the allocated new memory! But in case we use an array instead of a list
we have to make a different between static arrays where you know the size of an array and dynamic arrays where you
allocate new memory on the fly to write data in that array. Even an static array is nothing but less than a pointer to block in the memory. 

In c++ if you allocate new memory the result will be a pointer to the first adress of the allocated memory block, Basta. What you do with that memory is up to you. In c# the gc would organize it, in c++you have to do it on your own. And that is the reason why you need pointer how otherwise could YOU manage Your memory if you don't know where it lies.

 

So pointers are not need it to send large data,  they are needed to adress any data in the memory. 

Edited by exOfde

Share this post


Link to post
Share on other sites

The first question you must ask is: "Why does everyone manages memory manually while there are dozens of garbage collecting mechanisms for C++?"

Usually, we manage memory by hand because automatic managing won't be sufficient.

 

So, we manage memory by hand to avoid automatic managing problems. Examples are the implicit overhead and some implementations that arbitrarily pauses your program to clean up.

Specialization is an even common reason for manual memory management, specialized memory pools and management implementations are way too common on game development. Usually to avoid wasting memory (duplicates), reloads (having to load an asset prematurely purged due to lack of references), runtime overhead and possible pauses. It also affects the determinism of your software, not an issue on most cases.

 

But managing memory manually means keeping track of everything you have allocated, and the only reference you can have is a pointer. A pointer is nothing more than an address to the start of a memory block. If the memory in the said block has been used, and won't be used again, you can simply free it so other programs (or your own) can use it. The argument against manual memory management that you can create bad code and mess up exists, but I don't like to assume bad practices.

 

About your code, if you create an identical, it'll probably work just the same way.

So, I must assume you're referring to static arrays?

Edited by dejaime

Share this post


Link to post
Share on other sites

C# Version

class Program
    {
        static void Main(string[] args)
        {
            List<int> numberArray = new List<int>();
            Random rnd = new Random();
 
            for (int i = 0; i < 10000000; i++)
            {
                numberArray.Add(rnd.Next());
            }
        }
    }

C++ Version (pointers are hidden in the vector, just like they are in the C# List)

#include <vector>
#include <cstdlib>
 
int main()
{
   //  Dynamically allocated array
   std::vector<int> numberArray;
   //  Pre-allocate enough space for the ints, to prevent additional allocations and swapping
   numberArray.reserve(10000000);
   for (int i = 0; i < 10000000; i++)
   {
      numberArray.push_back(std::rand());
   }
   return 0;
}

[edit]

See previous answers for the why.  This is the equivalent C++ program.

Edited by Rattrap

Share this post


Link to post
Share on other sites

I generally don't need to think much about memory management in C++, because most of the time I don't use pointers explicitly. I just use standard containers (of objects, not pointers) and local variables that clean up after themselves. I was going to post code identical to Rattrap's, so you can just look at his example: He is using the same style I just described, and memory management is not an issue.

Edited by Álvaro

Share this post


Link to post
Share on other sites

EDIT: Sorry, to be more specific i'm not actually asking about code specifically, but why and where variables are assigned to heap verses stack. 

 

 

In case we use identical code, it would mean stl would do all the memory work you would never get in touch.

By the way a list is something different than an array.

But internal of the stl lib, the lib use a pointer to the allocated new memory! But in case we use an array instead of a list
You have to make a different between static arrays where you know the size of an array and a dynamic array where you
Allocate new memory on the fly to write data in that array. Even an static array is nothing but less a pointer to field in the memory. 

In c++ if you allocate new memory the result will be pointer the first adress of the allocated memory area, Basta. What you do with that memory
Is up to you. In c# the gc would organize it, in c++you have to do it on your own. And that is the reason why you need pointer how otherwise could YOU manage
Your memory if you don't know where it lies.

Sorry, not quite up with the C++ libraries, so that's a little hard to understand..

 

And that is the reason why you need pointer how otherwise could YOU manage

Your memory if you don't know where it lies

 

 

That's kinda core to my question, Non pointer variables get allocated to the stack and their memory is managed by going out of scope? and Pointers Allocate data to the Heap and are managed by the programmer?

 

 

C++ (im still not very good with the syntax..)

 

#include "stdafx.h"


void functionA(){
int a = 1; //Allocated to stack?
}
void functionB(){
int *ptrB = new int(100); //Allocated to heap?
delete ptrB;
ptrB = NULL;
}


int _tmain(int argc, _TCHAR* argv[])
{
functionA();
functionB();
return 0;
}

So, for another example/question: (again my c++ is very new)

void functionA(){
int array1 [6];
for (int i = 0; i < 6; i++)
{
array1[i] = 1;
}
}
void functionB(){


int array2[6];
int *ptrArray2 = &array2[0];


for (int i = 0; i < 6; i++)
{
*(ptrArray2+i) = 1;
}
}


int _tmain(int argc, _TCHAR* argv[])
{
functionA();
functionB();
return 0;
}
Where is the memory allocated?, Why use one function over the other?
Edited by Mellkor

Share this post


Link to post
Share on other sites

 

 

That's why you need pointers? to send large or persistent data to the heap and not overload the stack?

 

If you write normal object-oriented code, C++ pointers are used just like C# object references. It's a reference to an object allocated on the heap with the new operator. And the C++ & references are more like ref arguments.

 

But C++ pointers support additional operations, such as adding a number to it to get the pointer to the next object in memory, or subtraction two pointers to get the "distance" or "count".  With these operators you can iterate or traverse an array of objects in memory, it doesn't matter if they are on the stack or on the heap. Note that the iterators of the standard containers behave pretty much in the same way as pointers (though some of them do some automagic hocus pocus internally).

 

Pointers, references and memory management are very different in C+ and C#, so make sure you understand it really well. And then, as Álvaro said, understand how to use the standard containers etc. instead.

Share this post


Link to post
Share on other sites

and Pointers Allocate data to the Heap and are managed by the programmer?

 

Perhaps i misjudge you now but: 

I think you have don't understand what a pointer is. A pointer doesn't do anything; It just point to adress in the memory.

A Pointer can't allocate anything. In c++ only the operater new or the c-function malloc ( and all his friends ) can allocate memory.

 

 

In other words a pointer hold just an adress of an allocated memory block by new or malloc which you have to handle yourself.



void functionB()
{
    int *ptrB = new int(100); //here you ask for new memory 
                              //and the first adress of the memory
                              // block will be saved as adress in the pointer ptrB

    delete ptrB; // here you free all the memory again and the pointer is invalid
    ptrB = NULL; // pointer is  valid now because you set it to NULL
}

Edited by exOfde

Share this post


Link to post
Share on other sites

Using new to allocate memory will typically allocate to the heap (I don't believe this is a guarantee, since the stack/heap are memory management concepts not directly defined by C++ or other languages).  Plus there is placement new, which you can define where the memory is allocated (which you could point to an array on the stack).

 

A pointer itself is just a reference to a memory address.  In the case of allocating using new (or malloc for C), you are just storing the address returned by new/malloc.

 

Modern C++ lets us hide away some of the nastiness of the pointer as well.  You can use stl or stl like containers, which can handle the allocation and deallocation of the memory safely.  You can use smart pointers to essentially wrap a raw pointer in an object that will hide the raw pointer and handle deallocation automatically when all owners are done with it/goes out of scope.  This is similar to the garbage collection that you know, but you have a lot more control over when it occurs.  In C#, your at the mercy of the garbage collector when memory and resources are actually released.  In most cases, this is not really an issue.

Edited by Rattrap

Share this post


Link to post
Share on other sites

 


and Pointers Allocate data to the Heap and are managed by the programmer?

 

Perhaps i misjudge you now but: 

I think you have don't understand what a pointer is. A pointer doesn't do anything; It just point to adress in the memory.

A Pointer can't allocate anything. In c++ only the operater new or the c-function malloc ( and all his friends ) can allocate memory.

 

 

Sorry i should expressed that better, I understand that a pointer is just memory address, But you can use that to assign a value to the address by referencing.

I think where i have tripped up is like you say, the 'new' word actually does the memory allocation and not the declaration of the pointer/pointee

Edited by Mellkor

Share this post


Link to post
Share on other sites

Using new to allocate memory will typically allocate to the heap (I don't believe this is a guarantee, since the stack/heap are memory management concepts not directly defined by C++ or other languages).  Plus this is placement new, which you can define where the memory is allocated (which you could point to an array on the stack).

 

A pointer itself is just a reference to a memory address.  In the case of allocating using new (or malloc for C), you are just storing the address returned by new/malloc.

 

Modern C++ lets us hide away some of the nastiness of the pointer as well.  You can use stl or stl like containers, which can handle the allocation and deallocation of the memory safely.  You can use smart pointers essentially can wrap a raw pointer in an object that will hide the raw pointer and handle deallocation automatically when all owners are done with it/goes out of scope.  This is similar to the garbage collection that you know, but you have a lot more control over when it occurs.  In C#, your at the mercy of the garbage collector when memory and resources are actually released.  In most cases, this is not really an issue.

 

Thank you (and others) that example was pretty easy to understand

 I think i understand this now. only question i have is the array question above that's already partially answered.

Edited by Mellkor

Share this post


Link to post
Share on other sites
void functionA(){
int a = 1; //Allocated to stack? (YES)
}
void functionB(){
int *ptrB = new int(100); //Allocated to heap? (YES)
delete ptrB;
//  unnecessary, since it is going out of scope.
ptrB = NULL;
}

int _tmain(int argc, _TCHAR* argv[])
{
functionA();
functionB();
return 0;
}
void functionA(){
//  This is a stack allocation
int array1 [6];
for (int i = 0; i < 6; i++)
{
//  array1 is a pointer to address of the first element of the array.  array1[x] is the same as *(array1 + x)
array1[i] = 1;
}
}
void functionB(){
 
// See above, they are the same.
int array2[6];
int *ptrArray2 = &array2[0];

for (int i = 0; i < 6; i++)
{
*(ptrArray2+i) = 1;
}
}

int _tmain(int argc, _TCHAR* argv[])
{
functionA();
functionB();
return 0;
}

[edit]

Fixed some terminology.

Edited by Rattrap

Share this post


Link to post
Share on other sites

Please, post your question about arrays again. It's not entirely clear to me what you are referring to.

#include "stdafx.h"

void functionA(){
	int array1 [6];
	for (int i = 0; i < 6; i++)
	{
		array1[i] = 1;
	}
}
void functionB(){

	int array2[6];
	int *ptrArray2 = &array2[0];
	
	for (int i = 0; i < 6; i++)
	{
		*(ptrArray2+i) = 1;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	functionA();
	functionB();
	return 0;
}

Why should i use one function over the other? which is better/why?

Share this post


Link to post
Share on other sites

Here's a question for you.  Do you understand what the Stack and Heap are, and how programs use them to execute code?  That's really an essential part of fully understanding pointers and memory management.

 

My understanding is:

 

The stack, is a division of memory which is quite small in relation to the heap. Variables are pushed on to the heap when they are needed and removed when they go out of scope.(ie when a function ends)

 

The heap on the other hand is a large container of memory that is managed by the programmer. the Heap holds (or should) variables that have a long life cycle or quite large in size.

 

In my initial post, I did kinda ask in a roundabout way if you could crash a program by filling up the stack. and if you should strategically offload to the heap

Edited by Mellkor

Share this post


Link to post
Share on other sites

You can cause a stack overflow if you allocate too much memory on the stack either by:

1. Doing a huge stack allocation like int[ONE_BILLION]

2. Doing many smaller stack allocations, which can happen as a result of deep recursion (the stack allocations will stack as you recurse deeper)

 

However, it is not possible in the way shown in your example because it is not possible to have a dynamically sized array on the stack (which you could resize and then eventually run out of stack). You normally do only fixed size allocations on the stack (case 1). It is possible to allocate a block of run time determined size on the stack using alloca, but this is rare and used basically for optimization only.

 

The dynamically resizeable containers are implemented such that they use the heap to store their memory such that a memory block(s) of a different size can be acquired when needed.

Share this post


Link to post
Share on other sites


In my initial post, I did kinda ask in a roundabout way if you could crash a program by filling up the stack. and if you should strategically offload to the heap

 

Stack overflows are a fairly common runtime crash.  In many cases it's a bug in the code (ex. recursive function without a terminating condition).  If you're allocating large arrays on the stack though, that'd be a case where they'd likely have to get allocated on the heap. It may also be possible to declare such variables static, though that's rarely an appropriate option.

 

Also, the stack doesn't have to be quite small in relation to the heap.  In fact, it doesn't even have to be restricted to a specific size, though most environments these days do set such a restriction.  It's primarily done to prevent the stack and heap from stepping on each other.  While conceptually they're considered separate blocks of memory, the reality is most of the time they're just separate ends of the same block of memory.  The heap working from 'the bottom up', and the stack working from 'the top down'.

 

A dynamic stack is possible, but it's difficult to make sure the stack and heap don't step on each other's toes, whereas setting a specific stack size sets a very easy to monitor barrier with minimal downsides, and a stack overflow is much easier to resolve than the memory corruption that could otherwise occur.

 

All of that is fairly peripheral to how pointers work and are used, but it's all still useful knowledge to have when working in unmanaged environments.

Share this post


Link to post
Share on other sites

This topic is 1454 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this