How do I tell if I am using VLA (Variable Length Array)? - c++

I am on a project where we have to read in from a file, temporarily store them in dynamically allocated memory, do sorting and stuff, and deallocate the memory.
As per the project is testing our knowledge over dynamic memory and memory leak, one of the instructions is do not use VLA.
I am not sure what our instructor means by we should not use VLA, are we not allowed use [] bracket syntax? or we can use them as long as we use memories from heap and deallocate them properly once they are of no use anymore.
Here is my main.cpp, it is not complete yet, so please excuse some typos and possible errors, but if you have something to suggest or correct, those are more than welcome as well.
Thank you and do have a good weekend y'all.
#include "proj2-arrayFunctions.h"
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
ifstream file;
int size = 0;
int* numberArray;
int counter = 0;
file.open("arrays.txt");
if (!file)
{
cout << "error: file is not opened! " << endl;
return 1;
}
while(file.good())
{
file >> size;
numberArray = new int[size];
for (int i = 0; i < size; i++)
{
file >> numberArray[i];
}
bubbleSort(numberArray, size);
cout << "the largest value from this array is: " << largestValue(numberArray, size) << endl;
cout << "the smallest value from this array is: " << smallestValue(numberArray, size) << endl;
cout << "the average value of this array is: " << averageValue(numberArray, size) << endl;
cout << "the median value of this array is: " << medianValue(numberArray, size) << endl;
delete[] numberArray;
}
return 0;
}

int *numberArray; numberArray = new int[size]; is not a variable-length array, it's a dynamically allocated array. That's fine. Note that you have to delete[] it when done, which you do.
A VLA declaration would look like int numberArray[size]; where size is not a constant. It gets automatically deallocated when it goes out of scope, so you don't use delete on it. They are typically allocated on the stack and so can be created and deallocated very fast, but have various pitfalls. The main one is that there is no way to check if enough stack space is available, and your program will simply crash if there isn't; there is no way to safely detect or handle that error. So you would have to be very careful about checking that the value of size is reasonable.
VLAs are not part of standard C++, but some compilers support them anyway.

If you want to avoid using VLAs, use the appropriate compiler flag to treat VLAs as errors, which would be -Werror=vla for GNUC (gcc, clang, icc, et cetera). MSVC doesn't support VLAs anyway.

Related

C++ Displaying a Vector when using a pointer

#include <iostream>
#include <vector>
int main()
{
unsigned int numVec;
unsigned int input;
std::cout << "Enter Number of Vectors: ";
std::cin >> numVec;
std::vector<int>* Vec;
for (unsigned int i = 0; i < numVec; i++)
{
std::cout << "Enter Vector Value " << i << ": ";
std::cin >> input;
Vec->push_back(input);
}
std::cout << std::endl;
for (unsigned int i = 0; i < Vec->size(); i++)
{
std::cout << "Value at Index (" << i << ") " << Vec->at(i) << std::endl;
}
std::cout << std::endl;
return 0;
}
I am trying to learn how Vectors work as it is a topic that i have withheld learning for a very long time for no apparently reason.
My above code will compile and run however once i put in a number to store in the Vector it will crash.
The program did work before when i was just using a vector without the pointer but just for learning reasons i wanted to try it with a pointer, I am just wondering what am i doing wrong with this code and if someone could possibly flame me for doing something or give me some good advice on what i am doing wrong in this situation so i can learn for future reference.
Replace
std::vector<int>* Vec;
with
std::vector<int> vec;
and replace the pointer to member operator -> with the member selection operator ..
Only on rare occasions do you need to use dynamic storage for a std::vector instance, as that class does an excellent job of managing the memory for you. Currently you are not allocating any memory for your vector, and the behaviour of your code is undefined.
If you must use a pointer then write
std::vector<int>* vec = new std::vector();
and don't forget to call delete vec; when you're done. Consider using std::unique_ptr &c. so the delete is taken care of automatically.
My above code will compile and run however once i put in a number to store in the Vector it will crash.
What vector?
You never created a vector.
You only created a pointer, one which (a) is uninitialised, and (b) does not point to anything, let alone a (c) vector.

Output of an expanded array returns unexpected answer

I have finished writing a program that included reversing, expanding and shifting arrays using the pointer requirement asked by the professor. Everything compiles but the answer from the expand function does not return what I wish: adding 0s after the old user input array which asks for the size of the array and the numbers you wish to put into the array. I think my problem may lie from the fact that I include a pointer on something that might not have a reference in the program. Below is my code:
// *numPtr refers to my old user input array and int tamaño is the size of the array
void expandArray(int *numPtr, int tamaño) {
int *nuevoArray = new int[tamaño *2];
for (int i = 0; i<tamaño; i++) {
nuevoArray[i] = numPtr[i];
}
for (int i = tamaño; i < (tamaño*2); i++) {
nuevoArray[i] = 0;
}
std::cout << nuevoArray << " ";
}
As I said, my theory of the code not compiling the way I wish is because I use the *nuevoArray and it has no reference in my main code, but then again, I am just a beginner with C++. I was thinking of just doing a vector, but I think I would not follow the pointer requirements placed by the professor.
If you want to print the contents of nuevoarray, just use a for loop like this:
for (int i = 0; i < (tamaño*2); i++) {
std::cout << nuevoArray[i] << " ";
}
std::cout << "\n";
Also, since you are using new[] to create the array, you should not forget to delete[] it!
you can print your array by using
for (int i = 0 ; i < tamano * 2 ; ++i) {
std::cout << nuevoArray[i] << " ";
}
std::cout << std::endl;
or in c++11
for (auto i : nuevoArray) {
std::cout << i << " ";
}
std::cout << std::endl;
PS: The std::endl will return to the start of the new line and flush the cout buffer.
Your code does appear to be allocating a larger array and correctly copying data from numPtr into the new array and also correctly filling the remainder of the new array with zeros.
You don't explicitly say what you expect this function to output, but I'm guessing you expect it to print out the contents of the new array, and that you believe there's a problem because instead of that, you're seeing it print something like "0x7fb46be05d10".
You're not correctly printing the array out. Instead you're printing the memory address of the first element out. If you want to see the contents, then you need to loop over the elements of the array and print each one out individually.
Here's a function showing one way of doing that:
#include <algorithm>
#include <iterator>
void printArray(int *arr, int n) {
std::copy(arr, arr + n, std::ostream_iterator<int>(std::cout, " "));
}
Now you can replace the line std::cout << nuevoArray << " "; in your existing code with printArray(nuevoArray, tamaño*2);
(Also it sounds like whoever is teaching you C++ should take a look at this presentation from the recent C++ conference, CppCon 2015: Stop Teaching C)

C++ cin to c string dynamic allocation

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;
}

Difference between "size" and "capacity" in c++ string?

I have this snippet from Thinking in C++.
#include <iostream>
#include <string>
int main ()
{
string bigNews("I saw Elvis in a UFO. ");
cout << bigNews << endl;
bigNews.insert(0, " thought I ");
cout << bigNews << endl;
cout << "Size = " << bigNews.size() << endl;
cout << "Capacity = "
<< bigNews.capacity() << endl;
bigNews.append("I've been working too hard.");
cout << bigNews << endl;
cout << "Size = " << bigNews.size() << endl;
cout << "Capacity = "
<< bigNews.capacity() << endl;
return 0;
}
And I get output as shown below:
I saw Elvis in a UFO.
thought I I saw Elvis in a UFO.
Size = 33
Capacity = 44
thought I I saw Elvis in a UFO. I've been working too hard.
Size = 60
Capacity = 88
I can figure out why the size increases, but I am not able to make out how the Capacity increases?
What i know is Capacity is the string buffer where we can Pushback, but how that space is allocated?
capacity is the maximum number of characters that the string can currently hold without having to grow. size is how many characters actually exist in the string. The reason they're separate concepts is that allocating memory is generally inefficient, so you try to allocate as rarely as possible by grabbing more memory than you actually need at one time. (Many data structures use a "doubling" method where, if they hit their capacity of N and need more space, they will allocate 2*N space, to avoid having to reallocate again any time soon.)
capacity will increase automatically as you use the string and require more space. You can also manually increase it using the reserve function.
From the documentation:
capacity()
returns the number of characters that can be held in currently allocated storage
(public member function)
So, it is the allocation size of the internal buffer. What you see is its size doubling when it's exhausted -- this is a common technique for using dynamically-sized buffers efficiently, and it's called "exponential storage expansion". What it boils down to is basically this:
void resize_buffer(char **buf, size_t *cap, size_t newsize)
{
while (newsize > *cap)
*cap *= 2;
*buf = realloc(*buf, *cap);
}
(Of course, this is largely simplified, don't use this for actual reallocation code in production.) Probably your implementation of std::string is using this trick, that's why you see the buffer size going up by 100%.

How to get the size of the used space in an array? (NOT sizeof); c++

#include<iostream>
using namespace std;
int main()
{
char arr[200];
while(1) {
cin >> arr;
int i = sizeof(arr);
cout << "The arr input is "<< arr
<< " and the size of the array is "<< i << endl;
}
return 0;
}
For the input of 34,
This code outputs :The arr input is 34 and the size of the array is 200
while I want it to get the size of the used space of the array . So for The last input i want it to output :The arr input is 34 and the size of the array is 2
Can someone tell me how?
Maybe you want strlen(arr) here. It must be null terminated, otherwise the cout << arr would not have worked.
You would need to #include <cstring>
There's no automatic way to do what you want in the general case - you'll need to keep track somehow, either with your own counter, or by seeding the array with an 'invalid' value (that you define) and search for to find the end of the used elements (that's what the '\0' terminator character in a C-style string is).
In the example code you posted, the array should receive a null terminated C-style string, you can use that knowledge to count the number of valid elements.
If you're using C++ or some other library that has some more advanced data structures, you may be able to use one that keeps track of this kind of thing for you (like std::vector<>).
the size of the used space of the array
There is no such thing. If you have an array of 200 chars, then you have 200 chars. Arrays have no concept of "used" and "unused" space. It only works with C-strings because of the convention that those are terminated by a 0 character. But then again, the array itself cannot know if it is holding a C-string.
in a less involved manner, you can just count through each character till you hit a null with just a while loop. It will do the exact same thing strlen() does. Also, in practice, you should do type checking with cin, but i'll assume this was just a test.
#include <iostream>
using namespace std;
int main()
{
char arr[200];
int i;
while(1) {
cin >> arr;
i=0;
while (arr[i] != '\0' && i<sizeof(arr))
i++;
cout << "The arr input is "<< arr
<< " and the size of the array is "<< i << endl;
}
return 0;
}
Just for completeness, here is a much more C++ like solution that is using std::string instead of a raw char array.
#include <iostream>
#include <string>
int
main()
{
while (std::cin.good()) {
std::string s;
if (std::cin >> s) {
std::cout
<< "The input is " << s
<< " and the size is " << s.length()
<< std::endl;
}
}
return 0;
}
It doesn't use an array, but it is the preferable solution for this kind of problem. In general, you should try to replace raw arrays with std::string and std::vector as appropriate, raw pointers with shared_ptr (scoped_ptr, or shared_array, whatever is most appropriate), and snprintf with std::stringstream. This is the first step to simply writing better C++. You will thank yourself in the future. I wish that I had followed this advice a few years ago.
Try it
template < typename T, unsigned N >
unsigned sizeOfArray( T const (&array)[ N ] )
{
return N;
}