I have this code:
struct human
{
string name;
string adress;
string com_name;
string com_adress;
};
human **arr_human;
I need to allocate array of pointers.
I try it this:
arr_human = new human * [ 1000 ];
but I can't use this struct( example:
arr_human[0]->name = oName;
arr_human[0]->adress = oAddr;
arr_human[0]->com_name = cName;
arr_human[0]->com_adress = cAddr;
Why?
Like jrok said, you allocated the pointers but not the objects. You probably want to do something like this:
for (int i = 0; i < 1000; i++)
arr_human[i] = new human[numObjectsYouWant];
Since you're using C++, you might as well use vectors though. Does away with many of the problems you might encounter with using raw pointers.
vector<human> arr_humans;
Related
How do I delete the memory that have been allocated for array models, names? I tried every method but it always crashes when I run it.
int main()
{
vector<Person*> people;
const int PERSON_SZ = 4;
char * names[] = {"Jim", "Fred", "Harry", "Linda"};
int ages[] = { 23, 35, 52, 59 };
for (int i = 0; i < PERSON_SZ; i++)
{
Person * temp = new Person(names[i], ages[i]);
people.push_back(temp);
}
// A vector of Car pointers
vector<Car*> cars;
const int CAR_SZ = 3;
char * models[] = { "Festiva", "Ferrarri", "Prius" };
srand(time(0));
for (int i = 0; i < CAR_SZ; i++)
{
Car * temp = new Car(models[i]);
temp->set_driver(people[rand() % (people.size())]);
temp->set_owner(people[rand() % (people.size())]);
cars.push_back(temp);
}
for (int p = 0; p < people.size(); p++)
{
people[p]->increment_age();
}
for (int c = 0; c < cars.size(); c++)
{
cars[c]->print();
}
delete [] names;
for ( int r = 0; r < CAR_SZ; ++r )
{
delete [] models[r];
}
return 0;
}
You didn't allocate models and names using new, so you cannot delete them.
Both arrays are allocated on the stack and are automatically deleted, when the function returns.
The contents of the (string) arrays (i.e. the strings itselves) are stored in the global data segment and cannot be freed at all. This would also be dangerous because the compiler might use the same string constant at different places in the program.
The models array and the names array are both statically allocated. You didn't use new to create them, you don't need to delete them. You should, however, change their types as follows:
const char * names[] = {"Jim", "Fred", "Harry", "Linda"};
const char * models[] = { "Festiva", "Ferrarri", "Prius" };
because they are pointers to string literals, which are read-only.
The variable names and models are not dynamically allocated, and neither is the data in those arrays. So no need to free them or their contents.
The two vector contains data that need to be free'd on the other hand.
You did not allocate names, and models. You don't need to free or delete them from memory.
As others have answered, this is neither required nor legal...
delete [] names;
Since you didn't new names.
Neither is this...
for ( int r = 0; r < CAR_SZ; ++r )
{
delete [] models[r];
}
Since you didn't new any of the models.
But you do still have some memory leaks!
For each car instance you newed and stored in the cars vector, you need to call delete. Here is one way:
for (std::vector<Car*>::iterator car = cars.begin(), done = cars.end(); car != done; ++car)
{
delete *car;
}
Note that the * there dereferences the iterator, yielding the raw pointer you newed.
The problem with this approach is that it leaves you with a vector full of dangling pointers. You could either reset them in the loop or clear() the vector after the loop has terminated. Perhaps a better approach would be:
while (not cars.empty())
{
delete cars.back();
cars.pop_back();
}
Which deletes each car, then removes its pointer from the vector.
Similarly for each person you newed and stored in people:
while (not people.empty())
{
delete people.back();
people.pop_back();
}
As a rule of thumb, there should be one delete for every new and one delete[] for every new ... []. But you'll do well to learn about smart pointers.
names and models are not pointing heap-allocated area. Don't delete it.
Your code is incomplete. It does not compile. Please enable all warnings and debugging for your compiler, e.g. with g++ -Wall -g if using GCC and improve your code till you get no warning
char * names[] = {"Jim", "Fred", "Harry", "Linda"};
delete [] names;
This is incorrect. You can only delete something that you obtained thru new.
Environment: Windows 7 pro x64, Microsoft Visual Studio 2015 Enterprise, Version 14.0.25424.00 Update 3
int testFunction()
{
std::string _orig = "[188 80% (1/2)O:152]";
std::string _orig2 = "[999 99% (1/1)O:999]";
char *orig = NULL;
char *orig2 = NULL;
orig = new char[_orig.length() + 1];
strcpy(orig, _orig.c_str());
orig2 = new char[_orig2.length() + 1];
strcpy(orig2, _orig2.c_str());
*orig++;
*orig2++;
int a = atoi(orig);
int b = atoi(orig2);
delete[] orig;
delete[] orig2;
return 0;
}
Running the above code crashes with the "_CrtIsValidHeapPointer(block)" error.
If I don't iterate (*orig++ and *orig2++), then no issues.
So my question is, how can I iterate through the pointers and then when I'm done doing what I need to do with them, delete[] them correctly?
You did not delete the pointers you allocated!
delete must be called on the original memory address returned by new. Since you did orig++, you cant delete the address being pointed at!
Iterating can be done with an index, and using array subscription to dereference:
orig[i] = 'a';
Which is the same as doing this:
*(orig+i) = 'a';
Or you can get another pointer onto the same data, and modify this one.
char* pOrig = orig;
++pOrig;
Why did you write
*orig++; // why dereferencing?
Just ++ by itself would do the iteration.
Avoid to use raw pointers. Your code can be simpler:
std::string orig = "[188 80% (1/2)O:152]";
std::string orig2 = "[999 99% (1/1)O:999]";
int a = atoi(orig.c_str() + 1);
int b = atoi(orig2.c_str() + 1);
Your mistake is that you try to delete the shifted pointers instead of the original pointers. As the result heap manager gets wrong allocated block information usually put before the allocated pointer and you got heap corruption.
how can I iterate through the pointers and then when I'm done doing what I need to do with them, delete[] them correctly?
Create a copy of the pointer:
char* orig = new char[size];
char* i = orig;
*i++ = 'a';
delete orig;
A perhaps more common idiom is to dereference a temporary:
for(int i = 0; i < size - 1; i++)
orig[i] = 'a';
I would love to [use std::string], but I need to use atoi(), which won't work on std::string
You are mistaken. atoi works with std::string just fine. Simply use std::string::c_str() just like you did with strcpy. There is absolutely no reason to allocate a block of memory with new.
int testFunction()
{
std::string _orig = "[188 80% (1/2)O:152]";
int a = 0;
for (std::string::iterator it = _orig.begin(); it != _orig.end(); ++it)
{
if (isdigit((char)*it))
a = (atoi(it._Ptr));
}
return 0;
}
I got it. Thanks for everyone who helped me come to this conclusion. Staying with std::string was in fact the best approach.
I'm trying to allocate an array of pointers to a struct but there's something wrong with my code.
This is my struct:
struct Brick {
GameObject2D* handle_;
};
Brick** bricks_;
And this is how i'm trying to allocate memory for it:
int bricks_amount_ = 10;
bricks_ = (Brick**)malloc(sizeof(Brick*) * bricks_amount_);
The program crash. I've make a devenv on it to debug where's the problem and it crash on this line:
for (unsigned short int i = 0; i < bricks_amount_; i++){
bricks_[i]->handle_ = new GameObject2D(); <---------- CRASH!
}
Any suggestions?
PS: Sorry for my english :P
=========================================================================
[SOLUTION]
Finally i've decided to use std::vector instead raw pointers:
bricks_.resize(bricks_amount_);
but i've tried to make the malloc different way and it works too:
bricks_ = (struct Brick*)malloc(sizeof(struct Brick) * bricks_amount_);
or this:
bricks_ = new Brick[bricks_amount_];
Thank you to the people who wants to help!
It's C++:
don't use malloc, use new
don't use plain arrays, use std::vector or std::array
don't use raw pointers, use std::unique_ptr
Do not use
Bricks ** //will be a 2 dimensional array
Use instead
Bricks * //will be a 1 dimensioanal array
If you want a single dimensional array
Then do
`Bricks * bricks_ = (Bricks *)malloc(sizeof(Brick) * bricks_amount_ );
`
Then you can safely do without a crash
for (unsigned short int i = 0; i < bricks_amount_; i++){
bricks_[i]->handle_ = new GameObject2D(); <---------- There will not be CRASH!
}
I'm relatively new to C++ memory management, and I'm getting this weird error of heap corruption (plus an automatic breakpoint in Visual Studio before it). Here is the offending code:
z_world::z_world(char* name)
{
unsigned int i, skip;
char tmp;
//Load data from file
std::string* data = loadString(name);
//Base case if there is no world data
tiles = NULL;
w = 0;
h = 0;
if(data->length() > 0) {
//Set up the 'tiles' array
for(i = 0; i < data->length(); i++) {
if(data->at(i) == '\n')
h++;
if(h == 0)
w++;
}
tiles = new int[data->length()-h];
//Load Data
skip = 0;
for(i = 0; i < data->length(); i++) {
if(data->at(i) == '\n') {
skip++;
printf("\n");
continue;
}
tmp = data->at(i);
tiles[i+skip] = atoi(&tmp);
printf("%i ",tiles[i+skip]);
}
}
delete data;
}
Here's where I load in the string:
std::string* loadString(char* name)
{
ifstream in(name);
std::string* input = new string();
while(in) {
std::string line;
getline(in,line);
input->append(line);
input->append("\n");
}
in.close();
return input;
}
I get the breakpoint and error inside of "delete data;", which makes me think that "data" gets deleted somewhere before that, but I can't find where it would. For reference, this method is to create an object that contains world data for a game in the form of a virtual 2D integer array (for the ID's of the tiles).
Youre problem is probably here:
tiles[i+skip] = atoi(&tmp);
Problem 1:
It should be -skip
tiles[i - skip] =
Problem 2:
The atoi() command is being used incorrectly (tmp does not contain a string). But also I don't think atoi() is the appropriate method. I think what you are looking for is simple assignment. The conversion from char to int is automatic:
tiles[i - skip] = tmp;
Problem 3:
You are not using objects correctly. In this situation there is no need to generate dynamic objects and create a mess with dynamic memory management. It would be simpler to just to create automatic objects and pass those back normally:
std::string* loadString(char* name)
// ^ Don't do this.
std::string loadString(std::string const& name)
// ^^^^^^^ return a string by value.
// The compiler will handle memory management very well.
In general you should not be passing pointers around. In the few situations where you do need pointers they should be held within a smart pointer object or containers (for multiple objects) so that their lifespan is correctly controlled.
atoi(&tmp);
atoi expects a pointer to a null terminated string - not a pointer to a char
There's no need to dynamically allocate the string in the code you've shown. Change the loadString function to
std::string loadString(char* name)
{
ifstream in(name);
std::string input;
// ...
return input;
}
In the caller
std::string data = loadString( name );
Now there's no need to delete the string after you're done.
Instead of
int *tiles = NULL;
tiles = new int[data->length()-h];
use
std::vector<int> tiles;
tiles.resize(data.length() - h);
Also, if you do need to dynamically allocate objects you should be using smart pointers (std::unique_ptr and std::shared_ptr) instead of raw pointers.
There is a bug in
tiles[i+skip] = atoi(&tmp);
For example, for a string
Hello\n
World\n
and for the loop iteration at the point of i == 10, skip is already 1 (since we have encountered the first \n before) and you are writing to tiles[10 + 1], but tiles only has been allocated as an array with 10 elements.
May be the variable input is local to this function. So after returning from this the memory is freed. So, calling later delete on this string tries to free already freed memory.
How do I delete the memory that have been allocated for array models, names? I tried every method but it always crashes when I run it.
int main()
{
vector<Person*> people;
const int PERSON_SZ = 4;
char * names[] = {"Jim", "Fred", "Harry", "Linda"};
int ages[] = { 23, 35, 52, 59 };
for (int i = 0; i < PERSON_SZ; i++)
{
Person * temp = new Person(names[i], ages[i]);
people.push_back(temp);
}
// A vector of Car pointers
vector<Car*> cars;
const int CAR_SZ = 3;
char * models[] = { "Festiva", "Ferrarri", "Prius" };
srand(time(0));
for (int i = 0; i < CAR_SZ; i++)
{
Car * temp = new Car(models[i]);
temp->set_driver(people[rand() % (people.size())]);
temp->set_owner(people[rand() % (people.size())]);
cars.push_back(temp);
}
for (int p = 0; p < people.size(); p++)
{
people[p]->increment_age();
}
for (int c = 0; c < cars.size(); c++)
{
cars[c]->print();
}
delete [] names;
for ( int r = 0; r < CAR_SZ; ++r )
{
delete [] models[r];
}
return 0;
}
You didn't allocate models and names using new, so you cannot delete them.
Both arrays are allocated on the stack and are automatically deleted, when the function returns.
The contents of the (string) arrays (i.e. the strings itselves) are stored in the global data segment and cannot be freed at all. This would also be dangerous because the compiler might use the same string constant at different places in the program.
The models array and the names array are both statically allocated. You didn't use new to create them, you don't need to delete them. You should, however, change their types as follows:
const char * names[] = {"Jim", "Fred", "Harry", "Linda"};
const char * models[] = { "Festiva", "Ferrarri", "Prius" };
because they are pointers to string literals, which are read-only.
The variable names and models are not dynamically allocated, and neither is the data in those arrays. So no need to free them or their contents.
The two vector contains data that need to be free'd on the other hand.
You did not allocate names, and models. You don't need to free or delete them from memory.
As others have answered, this is neither required nor legal...
delete [] names;
Since you didn't new names.
Neither is this...
for ( int r = 0; r < CAR_SZ; ++r )
{
delete [] models[r];
}
Since you didn't new any of the models.
But you do still have some memory leaks!
For each car instance you newed and stored in the cars vector, you need to call delete. Here is one way:
for (std::vector<Car*>::iterator car = cars.begin(), done = cars.end(); car != done; ++car)
{
delete *car;
}
Note that the * there dereferences the iterator, yielding the raw pointer you newed.
The problem with this approach is that it leaves you with a vector full of dangling pointers. You could either reset them in the loop or clear() the vector after the loop has terminated. Perhaps a better approach would be:
while (not cars.empty())
{
delete cars.back();
cars.pop_back();
}
Which deletes each car, then removes its pointer from the vector.
Similarly for each person you newed and stored in people:
while (not people.empty())
{
delete people.back();
people.pop_back();
}
As a rule of thumb, there should be one delete for every new and one delete[] for every new ... []. But you'll do well to learn about smart pointers.
names and models are not pointing heap-allocated area. Don't delete it.
Your code is incomplete. It does not compile. Please enable all warnings and debugging for your compiler, e.g. with g++ -Wall -g if using GCC and improve your code till you get no warning
char * names[] = {"Jim", "Fred", "Harry", "Linda"};
delete [] names;
This is incorrect. You can only delete something that you obtained thru new.