I'm having trouble understanding arrays of pointers to structures. I created this simple example to try and understand them better. Although it compiles, I keep getting "BAD ACCESS" crashes (nonsense pointers) at the point shown below. Can anyone explain why this is wrong?
#include <iostream>
using namespace std;
struct complex_num {
double real_part;
double imag_part;
};
void init_complex(complex_num *element) {
element->real_part = -1.0; // <--- EXECUTION STOPS HERE.
element->imag_part = 1.0;
}
int main(int argc, char *argv[]) {
int n = 5;
complex_num *array[n]; // Allocates for an array of n pointers to
// the complex_num structure, correct?
for (int i = 0; i < n; i++) {
init_complex(array[i]);
}
return 0;
}
I know there are better ways to do this. I know this is very C in style. Please don't suggest a different data structure. I'm curious specifically about arrays of pointers to structures. Thanks!
You did not allocate memory for your complex_num objects, only for an array with pointers to it. So when you call init_complex, it operates on a pointer to an invalid location.
Try this:
for (int i = 0; i < n; i++) {
array[i] = new complex_num();
init_complex(array[i]);
}
Your statement complex_num *array[n] creates an array of n pointers to complex_num. Meaning, the array can hold n pointers to complex_num; but the pointers themselves are still uninitialized. They point to random locations - every uninitialized primitive (to which pointers belong as well) in C++ will usually simply contain whatever value was in the memory location before the allocation. This will almost certainly lead to unexpected results, as there is no way (or at least no reasonably easy way) of telling where an uninitialized pointer points to.
So you'd have to make each pointer in the array point to some properly set up memory location containing complex_num; only after that you should access (read or write) the values in the complex_num where the pointer points to. To make it e.g. point to a dynamically allocated, new complex_num object, use the above code (notice the new keyword which does the dynamic allocation).
Side note: "Raw" pointers, pointing to dynamically allocated objects, like shown above, are tricky to handle (you should not forget to call delete after you are finished, otherwise you will leak memory), therefore the recommended practice is usually to use smart pointers (like std::shared_ptr, introduced with C++11).
yes, there is no memory allocated to the pointers you have declared. It doesn't point to any valid structure object
Related
Consider the following code:
int *expand_array(int *old_arr,int array_length)
{
int *new_arr = new int[array_length +3];
for(int counter=0;counter<array_length;counter++)
new_arr[counter]=old_arr[counter];
delete[] old_arr;
return new_arr;
}
int main()
{
int *my_first_arr = new int[4];
int *my_expanded_arr=expand_array(my_first_arr,4);
delete[] my_expanded_arr;
}
will there be any memory leak here?
And to generalize the question,
if the pointer returned from a new statement is copied ,passed to a function or assigned to a different pointer, will the delete copied_pointer release the memory?
Your code is perfectly valid C++ and has no memory leaks. You can copy a pointer as often as you want to and deleteing any of those copies in any scope has the same effect.
It is still bad practice, however, and you shouldn't write code like this. Use of raw new and delete is too error prone and will make for poorly maintainable code. Instead, use RAII wrapper types like std::unique_ptr, std::shared_ptr or, in this case, std::vector.
The code in your question is basically equivalent to this.
int
main()
{
auto numbers = std::vector<int>(4);
numbers.resize(7);
}
Much simple, no?
Why do you believe that there would be a memory leak? Of course there wouldn't be.
But there is a different bug in this code. If the new array size is larger than the size of the existing old_arr, the code that copies the old array to the newly allocated int array is going to copy too much, run off past the end of the old array, resulting in undefined behavior; possibly a crash (old array size is 2 ints, array_length is 10, the for loop will attempt to copy 10 values from the old array which only has 2).
I am playing around with arrays as pointers.
#include<iostream>
#include<cstring>
using namespace std;
int main(){
string *myarray[20];
*myarray[0]="Ich denke sein";
*myarray[1]="Ich sehe sein";
cout<<*myarray[0]<<endl;
cout<<*myarray[1]<<endl;
return 0;
}
The above code compiles but while executing, there is error, the program hangs. When I debugged using visual studio, it said memory allocation error. What is the error here?
As I know, I am dealing with values refered by pointers everywhere.
You have allocated an array of 20 pointers to strings. But you haven't allocated any memory for what the pointers point to. Rather than pursuing this and using new to allocate memory for the strings, it would be better instead to allocate memory for the strings themselves in the array and you will be fine.
string myarray[20];
myarray[0]="Ich denke sein";
myarray[1]="Ich sehe sein";
cout<<myarray[0]<<endl;
cout<<myarray[1]<<endl;
In response to your comment, to make your program work as is, set the pointer to point to a new string object
myarray[0]=new string("Ich denke sein");
myarray[1]=new string("Ich sehe sein");
The other lines of your program remain unchanged. Note
the remaining myarray[i], for 2<=i && i<20 will still be garbage. (It would be neater to set them to 0 or nullptr in a for loop.)
you also ought to delete the objects you've allocated. (You could use a for loop over the whole array to do this if you'd cleared the rest of the pointers first.)
as other answers have commented, in modern C++ it is best not to use pointers directly unless you absolutely have to. And you would also typically prefer to use a vector for arrays rather than using the built-in type (in C++11 the array type can be used for arrays where you know the length at compile time).
You have an array of uninitialized pointers:
string *myarray[20];
Then you treat it as if the pointers pointed to valid objects:
*myarray[0]="Ich denke sein";
This is undefined behaviour. It is unrelated to arrays. It is the same as doing this:
std::string* s;
*s = "boom!";
Besides that, you really should #include <string> if you want to use std::string.
First, you didn't include the right header. For string, you should:
#include <string>
Second, the program hangs because you're assigning data to where the pointer is pointing to. So where does myArray[0] point to? You don't know, I don't know, no one knows. It seems you didn't get the grasp of what pointers are all about, regardless of whether you're dealing with arrays of them or not.
To use a pointer, it must point somewhere valid. If you don't do that, then you can't dereference the pointer and assign data. It's that simple.
May be the problem is that those pointers aren't pointing to any addres in the memory. Pointers should be initialized to somewhere using the "address of operator" (&) or putting them in the free memory, using the "new" keyword, and if you do so, don't forget to free that memory using the "delete" keyword. Hope that works for you.
What is the error here?
The error is, that you are using pointers ;-)
#include <string>
#include <iostream>
int main() {
std::string myarray[2] = {
{ "Ich denke sein" }, { "Ich sehe sein" } };
std::cout << myarray[0] << std::endl;
std::cout << myarray[1] << std::endl;
return 0;
}
What is the reason behind using pointer? In C++ you mostly never use pointers.
Kind regards - Andreas
You have declared an array of 20 pointers. You will have to allocate memory to the pointer before assigning a value at the location to which it points.
string* myarray[20];
for(int i = 0; i < 20; i++) {
myarray[i] = new string();//allocating memory to the pointer
}
*myarray[0]="Ich denke sein";
*myarray[1]="Ich sehe sein";
cout<<*myarray[0]<<endl;
cout<<*myarray[1]<<endl;
Pointers are used to point to memory addresses, like this:
String text ="hello";
String *myptr = &text;
Now the pointer points to the address of the string text.
Or you can use new keyword to allocate memory for an array of pointers. new returns you a pointer to the first position of the array. Like this:
int *myptr = new int[20];
But remember to use delete, to deallocate the allocated memory later. Like this:
delete[] myptr
I have a quick question regarding the scope of dynamic arrays, which I assume is causing a bug in a program I'm writing. This snippet checks a function parameter and branches to either the first or the second, depending on what the user passes.
When I run the program, however, I get a scope related error:
error: ‘Array’ was not declared in this scope
Unless my knowledge of C++ fails me, I know that variables created within a conditional fall out of scope when when the branch is finished. However, I dynamically allocated these arrays, so I cannot understand why I can't manipulate the arrays later in the program, since the pointer should remain.
//Prepare to store integers
if (flag == 1) {
int *Array;
Array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char *Array;
Array = new char[input.length()];
}
Can anyone shed some light on this?
Declare Array before if. And you can't declare array of different types as one variable, so I think you should use to pointers.
int *char_array = nullptr;
int *int_array = nullptr;
//Prepare to store integers
if (flag == 1) {
int_array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char_array = new char[input.length()];
}
if (char_array)
{
//do something with char_array
}
else if (int_array)
{
//do something with int_array
}
Also as j_random_hacker points, you might want to change you program design to avoid lot's of if
While you are right that since you dynamically allocated them on the heap, the memory won't be released to the system until you explicitly delete it (or the program ends), the pointer to the memory falls out of scope when the block it was declared in exits. Therefore, your pointer(s) need to exist at a wider scope if they will be used after the block.
The memory remains allocated (i.e. taking up valuable space), there's just no way to access it after the closing }, because at that point the program loses the ability to address it. To avoid this, you need to assign the pointer returned by new[] to a pointer variable declared in an outer scope.
As a separate issue, it looks as though you're trying to allocate memory of one of 2 different types. If you want to do this portably, you're obliged to either use a void * to hold the pointer, or (less commonly done) a union type containing a pointer of each type. Either way, you will need to maintain state information that lets the program know which kind of allocation has been made. Usually, wanting to do this is an indication of poor design, because every single access will require switching on this state information.
If I understand your intend correctly what you are trying to do is: depending on some logic allocate memory to store n elements of either int or char and then later in your function access that array as either int or char without the need for a single if statement.
If the above understanding is correct than the simple answer is: "C++ is a strong-typed language and what you want is not possible".
However... C++ is also an extremely powerful and flexible language, so here's what can be done:
Casting. Something like the following:
void * Array;
if(flag1) Array = new int[len]
else Array = new char[len];
// ... later in the function
if(flag) // access as int array
int i = ((int*)Array)[0];
Yes, this is ugly and you'll have to have those ifs sprinkled around the function. So here's an alternative: template
template<class T> T foo(size_t _len)
{
T* Array = new T[_len];
T element = Array[0];
return element;
}
Yet another, even more obscure way of doing things, could be the use of unions:
union int_or_char {int i; char c;};
int_or_char *Array = new int_or_char[len];
if(flag) // access as int
int element = Array[0].i;
But one way or the other (or the third) there's no way around the fact that the compiler has to know how to deal with the data you are trying to work with.
Turix's answer is right. You need to keep in mind that two things are being allocated here, The memory for the array and the memory when the location of the array is stored.
So even though the memory from the array is allocated from the heap and will be available to the code where ever required, the memory where the location of the array is stored (the Array variable) is allocated in the stack and will be lost as soon as it goes out of scope. Which in this case is when the if block end. You can't even use it in the else part of the same if.
Another different code suggestion from Andrew I would give is :
void *Array = nullptr;
if (flag == 1) {
Array = new int[input.length()];
} else if (flag == 2) {
Array = new char[input.length()];
}
Then you can directly use if as you intended.
This part I am not sure : In case you want to know if its an int or char you can use the typeid literal. Doesn't work, at least I can't get it to work.
Alternatively you can use your flag variable to guess what type it is.
there is no problem here:
int *x;
x = (int *) malloc(0 * sizeof(int));
int value = 5;
x = (int *) realloc(x,(value)*sizeof(int));
But I cant do that for strings :\
I wanna do that for a y[] array, like this:
y[0]="hello"
y[1]="how are you"
how can I do that?
std::vector<std::string> y;
y.push_back("hello");
y.push_back("how are you");
Don't use malloc, or realloc, or free in C++. Don't use char* for purposes other than interop. Stay away from pointers until you actually need them (same for arrays).
You cannot use realloc on an array of std::string objects because realloc moves things around by bit copying and this is not allowed on general objects.
The standard class std::vector is a generic container for objects that moves and copies things around correctly (using copy constructors, assignments and similar methods) and that can change its size for example with the resize method. All the needed memory is allocated and freed automatically as needed.
With std::vector for example you can write code like...
std::vector<std::string> v; // An empty vector
v.resize(10); // Now size is 10 elements (all empty strings "")
v[0] = "Hello"; // First element is now the string "Hello"
v[1] = "world."; // Second element is now the string "world."
v.resize(2); // Now v.size() is 2
v.push_back("How's going"); // Now the size is 3 and third element is filled.
Do yourself a favor and pick up a good C++ book, reading it cover to cover. C++ is a powerful but complex language and if you try to learn it by experimenting with a compiler you're making a terrible mistake for many reasons.
What you're doing right now is not C++ ... you can do what you want with C-style strings, but you would need an array of pointers to type char that allow you to access the allocated memory for each string in the array. This can be done like so:
char* y[2];
y[0] = strdup("hello");
y[1] = strdup("how are you");
You also need to keep in mind that your y array now "owns" the pointers, so you must call free() on each pointer in the array in order to avoid any memory leaks should you decide to change the strings each pointer is pointing to.
If you want to go with an idiomatic C++ solution though, and not revert to C-style strings, then you should be using std::string and std::vector ... doing so avoids the issues with memory leaks as well as allocating and deallocating the memory associated with dynamically allocated C-strings.
You can actually do exactly what you need exactly like with integers:
typedef const char *c_string;
c_string *y;
y = (c_string *) malloc(0 * sizeof(c_string));
int value = 5;
y = (c_string *) realloc(y,(value)*sizeof(c_string));
y[0]="hello";
y[1]="how are you";
This won't work with non-const char * though, so this example is of limited usability.
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.