// rememb-o-matic
#include <iostream>
#include <new>
using namespace std;
int main ()
{
int i,n;
int * p;
cout << "How many numbers would you like to type? ";
cin >> i;
p= new (nothrow) int [i];
if (p == 0)
cout << "Error: memory could not be allocated";
else
{
for (n=0; n<i; n++)
{
cout << "Enter number: ";
cin >> p[n];
}
cout << "You have entered: ";
for (n=0; n<i; n++)
cout << p[n] << ", ";
delete[] p;
}
return 0;
}
Now,
why is their a bracket enclosed in variable i?
p= new (nothrow) int [i];
why are their 2 for statements and what does a for statement do exactly?
Why is it deleting []p instead of the variable p?
why is their a bracket enclosed in variable i? &
Why is it deleting []p instead of the variable p?
p= new (nothrow) int [i];
Dynamically Allocates an int array of i elements .
delete []p;
Deletes the dynamically allocated array.
Basic Rules of dynamic allocation in C++ are:
If you use new to dynamically allocate memory, Use delete to deallocate it.
If you use new [] to dynamically allocate memory, Use delete [] to deallocate it.
Also, note that you are using nothrow version of the new operator, it basically returns a null if some error condition and does not throw an exception, this allows the C++ code to be compatible with the legacy c code which uses null check after memory allocations(malloc returns null on failure).
what does a for statement do exactly?
A for statement is a conditional loop construct, It keeps on executing the loop untill the condition remains true. The basic syntax of for loop is:
for(;condition;)
{
//doSomething
}
why are their 2 for statements?
The first for loop in your code gets the input from the user. It takes the input for i times.
The second for loop prints out the contents of the array.
Suggest you to pick up a good C++ book and read through the basics to understand more.
delete[] means that you are freeing an array back to the system, the no brackets for the if statement is optional and just means that the first line will be executed if true, I think you really need to learn some basics in C++ and programing in general, get a good book or google tutorials there are a lot of good ones out there
It is just C++ syntax.
new int [i] means that we want to allocate memory to store i integers.
delete [] p deletes memory bind to p. If [] are omitted, compiler assumes that p points to single instance of *p type. If instruction includes [] compiler tries to remove array of elements.
Related
This is a snippet of code that I took from a bigger one. I need to figure out whether or not what I'm printing is garbage and how to change it for it to print the value I need.
I need it to print the value of int id instead of whatever it's printing. The output was 10813776 in this run and it, of course, changes whenever I change some code or relaunch DevC++.
The code is:
#include <iostream>
#include <memory> //Memory allocation (malloc)
using namespace std;
int main(){
int id = 0;
int nMemory = 0;
int * pMemory;
pMemory = (int *) malloc(20 * sizeof(int));
while(id < 20){
if (pMemory != NULL){
cout << "Numbers in memory: " << endl;
pMemory = new int[id];
nMemory = *pMemory;
cout << nMemory << endl;
}
id++;
}
delete pMemory;
return 0;
}
pMemory = new int[id];
nMemory = *pMemory;
The first line replaces the array you've malloc-ed with a new uninitialized one, and then tries to read from the first slot of that new array. You shouldn't be assigning directly to pMemory; maybe to pMemory[someIndex], but not to pMemory itself.
Are you trying to read from the pMemory array and assign it to nMemory? If so, change the lines above to this:
nMemory = pMemory[id];
Your entire loop should look more like this:
if (pMemory != NULL) {
cout << "Numbers in memory: " << endl;
while(id < 20) {
nMemory = pMemory[id];
cout << nMemory << endl;
id++;
}
}
Or, with a more idiomatic for loop:
if (pMemory != NULL) {
cout << "Numbers in memory: " << endl;
for (int i = 0; i < 20; i++) {
cout << pMemory[i] << endl;
}
}
(You're also going to have to initialize the array somewhere above this loop. I presume you do that in your real code, but if not: the code you posted allocates an array with malloc() but does not set the items to useful values. Make sure to set them to something meaningful before you then try to read and print them.)
This code is leaking the memory blocks you allocate with malloc() and new[].
You malloc() a block of memory and assign its address to pMemory, then you change pMemory to point at different memory addresses that are allocated with new[]. So you lose the ability to free() the malloc()'ed memory (you are not even trying to call free()).
And, this code is not freeing the memory allocated with new[] correctly. Memory allocated with new[] must be freed with delete[], not with delete. Worse, you are calling new[] 20 times in a loop, but calling delete only once after the loop. So, you are leaking 19 blocks of new[]ed memory, and have undefined behavior freeing 1 block.
Now, to answer your actual question, the code is printing out garbage because the memory you are allocating with new[] is uninitialized, so the data you are trying to print from that memory contains indeterminate values.
Trying to figure out the reasoning behind the mechanics of c strings.
char** text;
text = new char*[5];
for(int i = 0; int < 5; int++) {
cout << endl << "Enter a phrase: ";
cin >> text[i];
cout << text[i];
}
I'm not entirely sure as to why this works for the first 2 iterations, even successfully displaying them, but gets a segfault error on the 3rd iteration.
You are using uninitialized memory. You are experiencing undefined behavior.
The line
text = new char*[5];
allocated memory for five pointers but those pointers haven't been initialized to point to anything valid. Before you can use text[i] to read data, you have to allocate memory for it.
for(int i = 0; int < 5; int++) {
cout << endl << "Enter a phrase: ";
text[i] = new char[SOME_SIZE_LARGE_ENOUGH_FOR_YOUR_NEED];
cin >> text[i];
cout << text[i];
}
Then, it should work.
You've allocated memory for 5 pointers, but you are not allocating anything that those five pointers point to. Assuming that you're using a modern 64-bit CPU with 8 byte-wide pointers, your new operator allocated exactly 40 bytes, five eight-byte pointers. Their initial contents are random, uninitialized memory, and when you write to them, they get interpreted as pointers to random memory addresses, which end up being corrupted with what you've read from std::cin. You got lucky initially, and the first two iterations scribbled over some memory somewhere, but your program continued to limp along, but you won the lottery on the third try; hitting a random address that does not exist, and segfaulting.
Although you can rewrite this to do proper allocation, if you're really trying to write C++, rather than C, here, there's no reason to allocate anything. Why do you want to deal with allocating memory, when C++ will happily do it for you?
std::vector<std::string> text;
for(int i = 0; int < 5; int++)
{
std::cout << std::endl << "Enter a phrase: ";
std::string s;
if (std::getline(std::cin, s).eof())
break;
text.push_back(s);
std::cout << s << std::endl;
}
I am creating a dynamic array inside a function. The code (posted below) runs without any problem. I am wondering if the way I have written is the right way to do it or if it will create problems in more complicated codes in the future. I am aware that the specific task my program (below) is trying to achieve is better effected with strings or vectors. But I created this artificial example to get my question across. however, if you strongly feel that dynamic arrays should be avoided, please feel free to share your opinion and the reasoning for it.
Result of my prior research: I was unable to find a coherent discussion on legality and morality of creating dynamic arrays using new [] and later deleting them in a different scope.
Thanks for your thoughts and insights.
My example code follows:
==========================
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
void getNonPunct(string _str, char* &_npcarr, int &_npsize);
int main()
{
string input_string;
char* npchar_arr;
int npsize;
cout << "Enter any string: ";
getline(cin, input_string);
getNonPunct(input_string, npchar_arr, npsize);
// Now display non-punctuation characters in the string
cout << "string with non-punctuation characters removed:\n";
for (int n = 0; n <= npsize - 1; n++)
cout << npchar_arr[n];
cout << "\n(" << npsize << ") non-punctuation characters\n";
// Now return the memory allocated with 'new' to heap
delete [] npchar_arr;
// Is it okay to 'delete' npchar_arr eve if it was created in the function
// getNonPunct() ?
return(0);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void getNonPunct(string _str, char* &_npcarr, int &_npsize)
//This void function takes an input array of strings containing arbitrary
//characters and returns a pointer to an array of characters containing only
//the non-punctuation characters in the input string. The number of
//non-punctuation characters are stored in size. Prior to the function call,
//int_arr and size are undefined. After the function call, char_arr points to
//the first location of an array of the non-punctuation character array.
//'size' is equal to the number of non-punctuation characters in the input
//string.
{
// First get the number of non-punctuation characters in the string
int str_len, npcount = 0;
str_len = static_cast<int>( _str.length() );
_npsize = 0;
for (int i = 0; i <= str_len - 1; i++)
{
if ( !ispunct(_str[i]) )
_npsize++;
}
// Now that you know how many non-punctuation characters are in the string,
// create a (dynamic) character array of _npsize.
_npcarr = new char [_npsize];
for (int k = 0; k <= str_len - 1; k++)
{
if ( !ispunct(_str[k]) )
_npcarr[npcount++] = _str[k];
}
return;
}
Is it valid? Yes. The array pointed to by npchar_arr exists until you destroy it and it is okay to destroy it using a delete[] expression in another function.
Is it a good idea? No. You would be much better off using a smart pointer that manages the lifetime of the object automatically, releasing you from the responsibility of delete[]ing the pointer manually yourself.
Consider using a std::unique_ptr<char[]> if your compiler and Standard Library support unique_ptr, or std::auto_ptr or std::shared_ptr if you cannot use unique_ptr (shared_ptr may also be found in Boost and C++ TR1).
Allocating in one scope and deleting in another is one of the major reasons for using dynamic allocation instead of an automatic local variable.
As James says, prefer to use smart pointers to track dynamically allocated objects.
The only constraint I can think of on allocation in one scope and deallocation in another is multi-component applications where different components are built with different compilers (or maybe different versions of the same compiler). On Windows, each compiler provides its own memory management library, and you shouldn't free memory from a different component than the one that allocated it. Or you can use Windows-provided memory management routines which are common to all compilers (e.g. HeapAlloc/HeapFree). On Linux, everyone uses the glibc-supplied malloc, free, new[], and delete[], so it isn't such an issue. For other OSes, you need to investigate.
This example is very trivial, but image the following modification of your code:
int main()
{
string input_string;
char* npchar_arr;
int npsize;
cout << "Enter any string: ";
getline(cin, input_string);
getNonPunct(input_string, npchar_arr, npsize);
// Now display non-punctuation characters in the string
cout << "string with non-punctuation characters removed:\n";
for (int n = 0; n <= npsize - 1; n++)
cout << npchar_arr[n];
cout << "\n(" << npsize << ") non-punctuation characters\n";
return(0); // WHOOPS! I JUST RETURNED AND DIDN'T FREE THE MEMORY
delete [] npchar_arr;
// Is it okay to 'delete' npchar_arr eve if it was created in the function
// getNonPunct() ?
return(0);
}
I just returned before freeing the memory, which results in a memory leak! Of course, you might be thinking that you would never do such a thing, but imagine a much more complex program, it is easy to make such a mistake as the above, and using smart pointers as the other answers suggest, would alleviate you of having to worry about such tasks.
How can I access elements from myVector like i would do with arrays ( for(i = 0; i < n; i++) cout << v[i] << " "; )
My code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Month
{
public:
char *name;
int nr_days;
Month(char* c, int nr) : name(c), nr_days(nr){};
~Month() { /* free(name); */}
};
int main()
{
Month January("January", 31);
Month February("February", 28);
Month March("March", 31);
Month April("April", 30);
Month May("May", 31);
Month June("June", 30);
Month July("July", 31);
Month August("August", 31);
Month September("September", 30);
Month Octomber("Octomber", 31);
Month November("November", 30);
Month December("December", 31);
vector<Month> *myVect = new vector<Month>;
myVect->push_back(January);
myVect->push_back(February);
myVect->push_back(March);
myVect->push_back(April);
myVect->push_back(May);
myVect->push_back(June);
myVect->push_back(July);
myVect->push_back(August);
myVect->push_back(September);
myVect->push_back(Octomber);
myVect->push_back(November);
myVect->push_back(December);
for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
{
/*
Month myMonth = i;
cout << myMonth.name << " " << myMonth.nr_days << endl;
*/
}
free(myVect);
return 0;
}
I would want to be something like a foreach algorithm: foreach(Month in myVect) cout << ...
And another question: why it gives me a run-time error at the destructor if I uncomment my line?
Ok, there are a lot of problems here.
You declare myVect as a pointer to a vector. This is unnecessary. One of the major benefits of using a vector is so that you don't have to worry about memory management as the vector does it for you. You stack allocate the vector, but internally it heap allocates the memory used to store the items it contains.
You never initialize the pointer. You are invoking undefined behavior as that pointer is not valid. To initialize a pointer you use new. All you have is an invalid stack allocated pointer that does not point to a vector on the heap. EDIT: I just realized that the new was edited out, so you can disregard this one. Still, it shouldn't be a pointer at all.
You are using free to deallocate a C++ class (that you never allocated to begin with...). Don't. This isn't C, you use new and delete to manage memory (when necessary!) in C++. free does not call destructors, it simply frees up a chunk of memory. delete on the other hand does as it knows how to deal with complex C++ types. Never mix new/delete with malloc/free.
myVect->begin() returns a const_iterator, not a T (i.e., in this case, not a Month object). Dereferencing the iterator via the * operator will yield the current iteration object, so:
Month myMonth = *i // <--- IMPORTANT!
As an aside, if you are going to be looping over the vector often you may want to typedef the iterator to reduce verbosity, i.e.,
typedef vector<Month>::const_iterator cmonth_iter;
Now you can write
for(cmonth_iter i = myVect.Begin(); i != myVect.end(); ++i )
{
Month m = *i;
// do stuff with m
}
You can access elements using iterator using the * operator:
for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
{
Month myMonth = *i;
cout << myMonth.name << " " << myMonth.nr_days << endl;
}
Also, you never allocate a vector in your code. You shouldn't use free() on a pointer you haven't received from malloc() earlier. It is undefined behavior to do otherwise and a run-time error is likely to occur at the point you call free().
Try this:
vector<Month> *myVect = new vector<Month>;
...
delete myVect;
If you remove the unitialized pointer bug by changing:
vector<Month> *myVect;
to:
vector<Month> myVect;
Then this will work. (Once you define ostream << Month)
for(i = 0; i < myVect.size(); i++)
cout << v[i] << " ";
You have a pointer myVect, but never assign a value to it before using (turn compiler warnings on). you should do something like myVect = new vector<Month>(). (or do not make it pointer and change -> into .). The rest of your "foreach" implementation looks fine. And you can use [] to access elements as well.
You free constant strings, you did not allocate them, so you need not to free them either.
You're declaring myVect as a pointer but never allocating it, that's going to give you lots of trouble. Just drop the * and you should be fine.
If you insist, you can use an index just like you would with an array:
for(int i = 0; i < myVect.size(); i++)
{
Month myMonth = myVect[i];
cout << myMonth.name << " " << myMonth.nr_days << endl;
}
Although I'd rather use iterators as you have done - just one simple fix:
Month myMonth = *i;
You can use the arrow operator with iterators...
for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
{
cout << i->name << " " << i->nr_days << endl;
}
note also that it's more idiomatic with iterators using ++i instead of i++ (the reason is that i++ will need to create a copy of the iterator that will be thrown away).
Note also that your code is UB (undefined behavior) because you are using a pointer to a vector, but you are not allocating it. By the way the use of a pointer in this case is nonsense, the code would be correct and simpler with:
vector<Month> myVect;
myVect.push_back(January);
myVect.push_back(February);
...
for(vector<Month>::const_iterator i = myVect.begin(); i != myVect->end(); ++i)
...
My suggestion is also to avoid to try learning C++ just by experimenting with a compiler (something that I've the impression you're trying to do).
C++ is powerful but also complex and unfortunately quite illogical and asymmetrical in many parts (due to its evolution history). Add to this that when you make a mistake (e.g. not allocating the vector in your original code) you cannot expect the compiler to help you and even at runtime the program may do ANYTHING, including apparently work as you expected (the worst possible thing). This combo is deadly.
Complexity, asymmetry and lack of runtime checks all make C++ impossible to learn by experimentation... just get a good book and read it. It's much simpler this way.
Again, I'm trying to make a simple program. It will read some kind of board, at the size of RxC. Each items on the board are letters, separated with spaces. This is a sample board:
A B C
D E F
G H I
After that, it will read an integer N, and for next N lines, read a string and process them one by one based on the given board. But now, I'm facing a problem with how to read them. Here is the code :
#include<iostream>
using namespace std;
int r,c,el; char **arr;
int main()
{
char *tes;
int n;
//start reading the puzzle
cin >> r >> c; el=r;
cout << el << endl;
arr = new char * [3*(r+c)-6];
for(int i=0;i<r;i++)
{
arr[i] = new char[c+1];
for(int j=0;j<c;j++) cin >> arr[i][j];
arr[i][c] = '\0';
}
for(int i=0;i<el;i++) cout << arr[i] << endl;
cin >> n;
while(n>0)
{
n--;
cin >> tes;
cout << tes << endl;
}
}
I don't know what's wrong with this, it's seems OK to me. However, it always get runtime errors. I'm using latest MinGW and gdb debugger. On gdb I saw something like
"received signal SIGSEGV. Segmentation
fault"
, and an 0xC0000005 error. I really have no idea what's going on here. I've tried both iostream(cin&cout) and cstdio(scanf,puts,etc.)
P.S.: I declare the variables globally, because I will process them on a different function out of the main() function. I set the size of the "height" of the array to (3*(r+c)-6), not to the normal (r) is because I will use the same array to store another strings later.
In addition to the problems already noted by others, you haven't allocated any memory for tes - it's just a dangling pointer.
Change:
char *tes;
to, e.g.:
char tes[80];
A board of size R*C needs, not very surprisingly, r*c chars of storage. I fail to understand why you're allocating the board in so many steps. A single char* board = new char[r * c]; should do it, then just keep track of where in the array your're reading.
Segmentation fault usually means you are trying to access memory which hasn't been allocated, for instance
char* mystr = (char*)malloc(3*sizeof(char));
mystr[4] = 0.0;
will (most likely) cause a seg fault because you're accessing memory which you didn't allocate (mystr goes from 0 - 2).
Are you sure you're allocating the memory correctly? I'm not sure why you have 3*(r+c)-6.
Further to unwind's answer, your array has size 3*(r+c)-6, but you are looping over values i = 0; i < r;, which depending on the values may just run out of bounds (plus it makes no sense).