This question already has an answer here:
C++ Struct Pointer Segfault
(1 answer)
Closed 9 years ago.
I'm new to C++ and pointers and wrote a simple cpp below. I keep on getting a seg fault, but I'm not sure why.
int main() {
int *x = 0;
*x = 8;
return 0;
}
Your integer pointer is null. See this line:
int *x =0
On that line you're setting the memory address of your integer pointer to zero (i.e. nullptr). What I expect you wanted to do is set the value to zero, in which case you'd need to do this:
int main() {
int *x = new int(0);
*x = 8;
return 0;
}
You've declared a pointer to an integer and set it to 0. You haven't actually allocated an integer anywhere. When you assign 8 to the dereferenced pointer, you're trying to write to the memory at location 0. All modern operating systems read and write product the memory at address 0 and anywhere near it to prevent this kind of 'null pointer error'.
Think of memory on a computer as a sheet of graph paper. Each square on the paper has an address, which is the number of squares that came before it. Pointers are for storing these addresses. An int is an actual value, like '5 apples' or '12 downvoting asshats'. These are the values that are stored by writing a number inside one of the rectangles.
However, the OS that manages the system knows that one of the most common kinds of errors people make is forgetting to set up a pointer properly and attempting to write numbers at the very start of the graph paper, so it's designed the graph paper to give you an electric shock if you try to write a number in any of the first few boxes. This is your segmentation fault.
To fix the issue you can either declare an integer on the stack
int i;
int * x = &i;
Declaring something on the stack means the memory will automatically be freed when it leaves scope, i.e. the end of the function.
On the other hand you can allocate a pointer on the heap
int * x = new int;
this means that you're personally responsible for making sure that you free the memory at some later point.
delete x;
Otherwise you're creating a memory leak.
When you define int *x = 0, what you're telling the compiler is "create a integer pointer, x, and set where it points to to 0 (NULL)". What you need to do instead is dynamically create a new pointer. This can be achieved by doing int *x = new int; Then you can change its value. After using it, you should delete it using delete x; to free up its memory.
int *x = 0;
You made an int pointer called x which points to the memory at location 0.
*x = 8;
You tried to write the value 8 into the memory at location 0, which was stored in x. Since this memory is not owned by you, the OS terminated you.
Let's break this down a bit:
int *x = 0
this line creates a pointer called x and points it to NULL (or nowhere)
*x = 8
There is an immediate issue here as soon as you "dereference" x, meaning asking for the spaces associated what x points to.
Since you pointed x at NULL you're asking for the int located at NULL. This is illegal as NULL is an invalid memory space causing a seg-fault.
Related
int main() {
int* i = new int(1);
i++;
*i=1;
delete i;
}
Here is my logic:
I increment I by 1, and then assign a value to it. Then I delete the I, so I free the memory location while leaking the original memory. Where is my problem?
I also tried different versions. Every time, as long as I do the arithmetics and delete the pointer, my program crashes.
What your program shows is several cases of undefined behaviour:
You write to memory that hasn't been allocated (*i = 1)
You free something that you didn't allocate, effectively delete i + 1.
You MUST call delete on exactly the same pointer-value that you got back from new - nothing else. Assuming the rest of your code was valid, it would be fine to do int *j = i; after int *i = new int(1);, and then delete j;. [For example int *i = new int[2]; would then make your i++; *i=1; valid code]
Who allocates is who deallocates. So you should not be able to delete something you did not new by yourself. Furthermore, i++;*i=1; is UB since you may access a restricted memory area or read-only memory...
The code made no sense . I think You have XY problem. If you could post your original problem there will be more chance to help you.
In this case you need to have a short understanding how the heap memory management works. in particular implementation of it, when you allocate an object you receive a pointer to the start of the memory available to you to work with. However, the 'really' allocated memory starts a bit 'earlier'. This means the allocated block is a bit more than you have requested to allocate. The start of the block is the address you have received minus some offset. Thus, when you pass the incremented pointer to the delete it tries to find the internal information at the left side of it. And because your address is now incremented this search fails what results in a crash. That's in short.
The problem lies here:
i++;
This line doesn't increment the value i points to, but the pointer itself by the number of bytes an int has (4 on 32-bit platform).
You meant to do this:
(*i)++;
Let's take it step by step:
int* i = new int(1); // 1. Allocate a memory.
i++; // 2. Increment a pointer. The pointer now points to
// another location.
*i=1; // 3. Dereference a pointer which points to unknown
// memory. This could cause segmentation fault.
delete i; // 4. Delete the unknown memory which is undefined
// behavior.
In short: If you don't own a piece of memory you can't do arithmetic with it neither delete it!
int main()
{
int *aligned;
// aligned value 0xcccccccc{???}
aligned = (int*)_aligned_malloc(sizeof(int) * 1000, 16);
// aligned value 0x001d9490{-842150451}
_aligned_free(aligned);
//// aligned value 0x001d9490{-17891602} address did not change
*aligned == 100;
int *y;
// y value 0xcccccccc{???}
y = new int();
// y value 0x001d9480{0}
delete(y);
// y value 0x00008123{???} address has changed
*y = 100; // Gives exception
}
My question:
Why code at line 4 does not give exception? Does it mean memory is not properly freed by _aligned_free? If yes, then how should we free memory allocated by _aligned_malloc.
The code at line 4 isn't doing anything - you are using == (test for equality) not = (assignment) on that line. Well, actually, it is doing something - it will attempt to read from an address in a memory block you just freed (and compare that value to 100). This might not necessarily cause an exception - many heap managers will carve chunks out of larger blocks allocated in your process address space, so freeing one might very well just mark the block as available for the heap manager to reuse. Reading/writing to this space after freeing might not cause an exception every time (because it might still be part of the valid heap space for the process), but it is definitely an error.
Also, after calling _aligned_free the pointer value (aligned) shouldn't change - that doesn't mean the memory was not freed.
int *aligned;
// aligned value 0xcccccccc{???}
You did not initialize the pointer, so it's got whatever garbage value was there before main started. Do int *aligned = NULL; if you want it to start off null.
aligned = (int*)_aligned_malloc(sizeof(int) * 1000, 16);
// aligned value 0x001d9490{-842150451}
Looks OK
_aligned_free(aligned);
//// aligned value 0x001d9490{-17891602} address did not change
None of the free calls changes the pointer passed in. Ever.
*aligned == 100;
As frasnian pointed out, this does a comparison and throws the result away. But even if you changed that to an assignment, you're dereferencing a freed pointer, which is undefined behavior. And that means anything could happen: it could work, it could crash, it could do something else unexpected.
int *y;
// y value 0xcccccccc{???}
Again, uninitialized.
y = new int();
// y value 0x001d9480{0}
Okay, you have a pointer to an int.
delete(y);
// y value 0x00008123{???} address has changed
That's unexpected. Might be a feature of your compiler. Might be an optimization reusing the register.
*y = 100; // Gives exception
Because you dereferenced a deleted pointer, and again you're in undefined behavior land. Apparently your platform does not like odd addresses for integers. Not all platforms throw exceptions here.
The rule is that a pointer that you have passed to free or delete is gone. Dead. An ex-pointer. Pushing up the bit-daisies. Pining for the fjords. It is no more.
There might be a value left over in the register, but it is no longer valid and should not be used. The compiler cannot be expected to catch the cases where you try to use a dead pointer.
By referring to http://www.cplusplus.com/doc/tutorial/dynamic/, it is said that the new operator returns a pointer to the beginning of the new block of memory allocated. Let's assume again that any pointer has the feature of pointer arithmetic, which can make it true that p + 1 points to the next position in memory if p is a pointer.
Based on the above assumptions, I have tried the following block,
#include <iostream>
using namespace std;
int main(){
int * ptr = (new int [4]) + 1;
ptr[3] = 2;
cout << ptr[3] << endl;
/*Before delete the dynamic allocated memory,
it should be necessary to let ptr point to the
beginning of it, add one line to do that:
--ptr;*/
delete [] ptr;
}
I expected that ptr[3] should goes beyond the range of newly allocated memory. However, the result still give 2. Why the pointer arithmetic become useless? Or is it really new Type returns an object of *Type?
Thanks for any help.
I expected that ptr[3] should goes beyond the range of newly allocated memory.
It does indeed. You need to be careful not to do that, since (as you've noticed) that's an error that often can't be detected. Dynamic analysis tools like valgrind can help diagnose these problems, but not perfectly.
However, the result still give 2.
That means that there happened to be accessible memory beyond the end of the array, so the invalid access couldn't be detected. Instead, it overwrote memory that didn't belong to the array - perhaps it was unused, or perhaps you've overwritten some other data, which will cause baffling errors later.
Why the pointer arithmetic become useless?
It's as useful as any pointer arithmetic. Pointer arithmetic can't detect the end of an array, so you get undefined behaviour if it takes you out of range.
Or is it really new Type returns an object of *Type?
new Type[] returns a Type* pointer to the allocated array. That behaves just like any other pointer, so adding one gives you a pointer to the second element.
delete [] ptr also gives undefined behaviour, since ptr no longer points to the start of an allocated array.
Going beyond boundary is undefined behavior.
You may get different results when compiled by differet compiler, different compilation flags, even running at different time. You computer may blow off and your monitor may burn.
Return a correct value is one of undefined behaviors too.
C/C++ allows you to assign/read values to/from out of bounds memory, as this is undefined behavior.
For instance, this is valid code:
int *array = new int[10];
array[10] = 5;
std::cout<<array[10];
However, doing this you could damage other data structures, if they happen to have memory allocated adjacent to your array.
int * ptr = new int [4];
will point to ptr[0], so
int * ptr = (new int [4]) + 1;
will pont to ptr[1] and you will not be able to free ptr unless you do something like delete (ptr--);
what is the difference between the following block of code :
#include<iostream>
using namespace std;
int main()
{
int *p;
float *q;
cout<<p<<"\n"<<q;
}
and this code :
#include<iostream>
using namespace std;
int main()
{
int *p;
float *q;
p = new int;
q = new float;
cout<<p<<"\n"<<q;
}
In both the cases the pointers are allocated some memory right?
Then why should i use the new operator?
No, int *p and float *p declare pointers, but they are not initialised, so they each point to a random address in memory. In particular, they do not point to memory space allocated to your program.
The second piece of code correctly allocates memory and stores the address of that memory in the two pointers. However, note that your code never de-allocates the memory, so you have a memory leak. You'd have to use delete p and delete q at the end of the program to avoid this.
To answer the question in your title a bit more directly: no, you do not have to use the new operator very often in C++; in fact, in well written code you usually use it quite rarely.
In this case, rather than using pointers at all, you would typically want to just define the int and float using the auto storage class, without defining any pointers or using new at all. While you're at it, most code shouldn't have using namespace std; in it either. Fixing those, you could end up with something like this:
#include<iostream>
int main()
{
int p = 1;
float q = 2.0f;
std::cout<<p<<"\n"<<q;
}
If your code has new and/or T *xxx very often (where T is some type and xxx is some identifier) chances are pretty good that it's not really a question of whether you're doing something wrong, only of how many things and how badly wrong.
In the first block of code, memory is allocated for the pointers themselves, but no memory is allocated which they can point to and validly use. The address that is printed out is not safe for your program to use.
The "pointer" variable does already being allocated in main() stack, 4 bytes in 32-bit or 8 bytes in 64-bit machines. The memory storage for int and float, which are pointed by p and q respectively, are not allocated yet in the first case. Your cout just prints out the memory address of p & q, not the value where p or q points to.
I've been reading through some books, and when it comes to Class/Functions using Pointers/Dynamic Memory (or heap or w/e they call it) I start to get confused.
Does anyone have a simple....like easy example they can show, because the books im using are using overly complex examples (large classes or multiple functions) and it makes it hard to follow. Pointers have always been my weak point anyways but I understand BASIC pointers, just classes/functions using them is a little bit confusing.
Also.....when would you use them is another question.
Stack allocation:
char buffer[1000];
Here the 1000 must be a constant. Memory is automatically freed when buffer goes out of scope.
Heap Allocation:
int bufsz = 1000;
char* buffer = new char[bufsz];
//...
delete [] buffer;
Here bufsz can be a variable. Memory must be freed explicitly.
When to use heap:
You don't know how much space you will need at compile time.
You want the memory/object to persist beyond the current scope.
You need a large chunk of memory (stack space is more limited than heap space)
Your computer's RAM is a big pile of bytes ordered one after another, and each one of those bytes can be accesed independently by it's address: an integer number startig from zero, upwards. A pointer is just a variable to hold that address of a single place in memory.
Since the RAM is a big chunk of bytes, the CPU ussually divides that big pile of bytes on several chunks. The most important ones are:
Code
Heap
Stack
The Code chunk is where the Assembly code lies. The Heap is a big pool of bytes used to allocate:
Global variables
Dynamic data, via the new operation on C++, or malloc() on C.
The stack is the chunk of memory that gets used to store:
Local variables
Function parameters
Return values (return statement on C/C++).
The main difference between the Stack and Heap is the way it is used. While the Heap is a big pool of bytes, the Stack "grows" like a stack of dishes: you can't remove the dish on the bottom unless there are no more dishes on it's top.
That's how recursion is implemented: every time you call a function recursively, memory grows on the stack, allocating parameters, local variables and storing return values of the returning functions, one on top of the others just like the stack of dishes.
Data living on the Stack have different "Life Span" than the data living on the Heap. Once a function exits, the data on the local variables get lost.
But if you allocate data on the Heap, that data won't get lost util you explicitly free that data with the delete or free() operations.
A pointer is basically a variable that contains the memory address of another variable (or in other cases to a function, but lets focus on the first).
That means that if I declare int[] x = {5,32,82,45,-7,0,123,8}; that variable will be allocated to memory at a certain address, lets say it got allocated on address 0x00000100 through 0x0000011F however we could have a variable which indicates a certain memory address and we can use that to access it.
So, our array looks like this
Address Contents
0x00000100 1
0x00000104 32
0x00000108 82
0x0000010B 45
0x00000110 -7
0x00000114 0
0x00000118 123
0x0000011B 8
If, for example, we were to create a pointer to the start of the array we could do this: int* p = &x; imagine this pointer variable got created a memory address 0x00000120 that way the memory at that address would contain the memory location for the start of array x.
Address Contents
0x00000120 0x00000100
You could then access the contents at that address through your pointer by dereferencing the pointer so that int y = *p would result in y = 1. We can also move the pointer, if we were to do p += 3; the pointer would be moved 3 addresses forward (note, however, that it moves 3 times the size of the type of object it is pointing to, here I am making examples with a 32 bit system in which an int is 32 bits or 4 bytes long, therefore the address would move by 4 bytes for each increment or 12 bytes in total so the pointer would end up pointing to 0x0000010B), if we were to dereference p again by doing y = *p; then we'd end up having y = 45. This is just the beginning, you can do a lot of things with pointers.
One of the other major uses is to pass a pointer as a parameter to a function so that it can do operations on certain values in memory without having to copy all of them over or make changes that will persist outside of the function's scope.
Warning: Don't do this. This is why we have vectors.
If you wanted to create an array of data, and return if from a function, how would you do it?
Obviously, this does not work:
int [10] makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
You cannot return an array from a function. We can use pointers to refer to the first element of an array, like this:
int * makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return &(arr[0]); // Return the address of the first element.
// Not strictly necessary, but I don't want to confuse.
}
This, however, also fails. arr is a local variable, it goes on the stack. When the function returns, the data is no longer valid, and now you have a pointer pointing to invalid data.
What we need to do is declare an array that will survive even after the function exits. For that, we use keyword new which creates that array, and returns the address to us, which needs to be stored in a pointer.
int * makeArray(int val)
{
int * arr = new int[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
Then you can call that function and use that array like this:
int * a = makeArray(7);
for(int i=0; i<10; ++i)
std::cout << a[i] << std::endl;
delete [] a; // never forget this. Obviously you wouldn't do it right
// away like this, but you need to do it sometime.
Using pointers with new also gives you the advantage that you can determine the size of the array at runtime, something you can't do with local static arrays(though you can in C):
int * makeArray(int size, int val)
{
int * arr = new int[size];
for(int i=0; i<size; ++i)
arr[i] = val;
return arr;
}
That used to be one of the primary purposes for pointers. But like I said at the top, we don't do that anymore. We use vector.
One of the last vestiges of pointers is not for dynamic arrays. The only time I ever use them, is in classes where I want one object to have access to another object, without giving it ownership of that object. So, Object A needs to know about Object B, but even when Object A is gone, that doesn't affect Object B. You can also use references for this, but not if you need to give Object A the option to change which object it has access to.
(not tested, just writing down. and keeping things intentionally primitive, as requested.)
int* oneInt = new int; // allocate
*oneInt = 10; // use: assign a value
cout << *oneInt << endl; // use: retrieve (and print) the value
delete oneInt; // free the memory
now an array of ints:
int* tenInts = new int[10]; // allocate (consecutive) memory for 10 ints
tenInts[0] = 4353; // use: assign a value to the first entry in the array.
tenInts[1] = 5756; // ditto for second entry
//... do more stuff with the ints
delete [] tenInts; // free the memory
now with classes/objects:
MyClass* object = new MyClass(); // allocate memory and call class constructor
object->memberFunction("test"); // call a member function of the object
delete object; // free the object, calling the destructor
Is that what you wanted? I hope it helps.
I think this is what you're asking about:
Basically C++ doesn't allow variable-sized arrays. Any array in C++ has to be given a very specific size. But you can use pointers to work around that. Consider the following code:
int *arry = new int[10];
That just created an array of ints with 10 elements, and is pretty much the same exact thing as this:
int arry[] = int[10];
The only difference is that each one will use a different set of syntax. However imagine trying to do this:
Class class:
{
public:
void initArry(int size);
private:
int arry[];
};
void class::initArry(int size)
{
arry = int[size]; // bad code
}
For whatever reason C++ was designed to not allow regular arrays to be assigned sizes that are determined at runtime. Instead they have to be assigned sizes upon being coded. However the other way to make an array in C++ - using pointers - does not have this problem:
Class class:
{
public:
~class();
void initArry(int size);
private:
int *arry;
};
class::~class()
{
delete []arry;
}
void class::initArry(int size)
{
arry = new int[size]; // good code
}
You have to do some memory cleanup in the second example, hence why I included the destructor, but by using pointers that way you can size the array at runtime (with a variable size). This is called a dynamic array, and it is said that memory here is allocated dynamically. The other kind is a static array.
As far as 2-dimensional arrays go, you can handle it kind of like this:
Class class:
{
public:
~class();
void initArrays(int size1, int size2);
private:
int **arry;
};
class::~class()
{
delete [] arry[0];
delete [] arry[1];
delete [] arry;
}
void class::initArrays(int size1, int size2)
{
arry = new int*[2];
arry[0] = new int[size1];
arry[1] = new int[size2];
}
Disclaimer though: I haven't done much with this language in a while, so I may be slightly incorrect on some of the syntax.