I have a function which returns a pointer to an array of doubles:
double * centerOfMass(System &system) {
long unsigned int size = system.atoms.size();
double x_mass_sum=0.0; double y_mass_sum=0.0; double z_mass_sum=0.0; double mass_sum=0.0;
for (int i=0; i<=size; i++) {
double atom_mass = system.atoms[i].m;
mass_sum += atom_mass;
x_mass_sum += system.atoms[i].pos["x"]*atom_mass;
y_mass_sum += system.atoms[i].pos["y"]*atom_mass;
z_mass_sum += system.atoms[i].pos["z"]*atom_mass;
}
double comx = x_mass_sum/mass_sum;
double comy = y_mass_sum/mass_sum;
double comz = z_mass_sum/mass_sum;
double* output = new double[3]; // <-------- here is output
output[0] = comx*1e10; // convert all to A for writing xyz
output[1] = comy*1e10;
output[2] = comz*1e10;
return output;
}
When I try to access the output by saving the array to a variable (in a different function), I get a segmentation fault when the program runs (but it compiles fine):
void writeXYZ(System &system, string filename, int step) {
ofstream myfile;
myfile.open (filename, ios_base::app);
long unsigned int size = system.atoms.size();
myfile << to_string(size) + "\nStep count: " + to_string(step) + "\n";
for (int i = 0; i < size; i++) {
myfile << system.atoms[i].name;
myfile << " ";
myfile << system.atoms[i].pos["x"]*1e10;
myfile << " ";
myfile << system.atoms[i].pos["y"]*1e10;
myfile << " ";
myfile << system.atoms[i].pos["z"]*1e10;
myfile << "\n";
}
// get center of mass
double* comfinal = new double[3]; // goes fine
comfinal = centerOfMass(system); // does NOT go fine..
myfile << "COM " << to_string(comfinal[0]) << " " << to_string(comfinal[1]) << " " << to_string(comfinal[2]) << "\n";
myfile.close();
}
Running the program yields normal function until it tries to call centerOfMass.
I've checked most possible solutions; I think I just lack understanding on pointers and their scope in C++. I'm seasoned in PHP so dealing with memory explicitly is problematic.
Thank you kindly
I'm not sure about the type of system.atoms. If it's a STL container like std::vector, the condition part of the for loop inside function centerOfMass is wrong.
long unsigned int size = system.atoms.size();
for (int i=0; i<=size; i++) {
should be
long unsigned int size = system.atoms.size();
for (int i=0; i<size; i++) {
PS1: You can use Range-based for loop (since C++11) to avoid such kind of problem.
PS2: You didn't delete[] the dynamically allocated arrays; Consider about using std::vector, std::array, or std::unique_ptr instead, they're designed to help you to avoid such kind of issues.
In addition to the concerns pointed out by songyuanyao, the usage of the function in writeXYZ() causes a memory leak.
To see this, note that centerOfMass() does (with extraneous details removed)
double* output = new double[3]; // <-------- here is output
// assign values to output
return output;
and writeXYZ() does (note that I've changed comments to reflect what is actually happening, as distinct from your comments on what you thought was happening)
double* comfinal = new double[3]; // allocate three doubles
comfinal = centerOfMass(system); // lose reference to them
// output to myfile
If writeXYZ() is being called multiple times, then the three doubles will be leaked every time, EVEN IF, somewhere, delete [] comfinal is subsequently performed. If this function is called numerous times (for example, in a loop) eventually the amount of memory leaked can exceed what is available, and subsequent allocations will fail.
One fix of this problem is to change the relevant part of writeXYZ() to
double* comfinal = centerOfMass(system);
// output to myfile
delete [] comfinal; // eventually
Introducing std::unique_ptr in the above will alleviate the symptoms, but that is more a happy accident than good logic in the code (allocating memory only to discard it immediately without having used it is rarely good technique).
In practice, you are better off using standard containers (std::vector, etc) and avoid using operator new at all. But they still require you to keep within bounds.
Related
#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.
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)
I am learning fftw (replace the self-defined fft function) in c++. In the old code, I have the algorithm designed in std::vector samples storage. According to the document, I use casting to interact the fftw datatype to my data (in std::vector).
#include <fftw3.h>
#include <vector>
#include <iostream>
#include <complex>
using namespace std;
void main(void)
{
std::vector< complex<double> > x(4);
x[0] = std::complex<double>(0.0, 0.0);
x[1] = std::complex<double>(1.0, 0.0);
x[2] = std::complex<double>(0.0, 2.0);
x[3] = std::complex<double>(3.0, 3.0);
// print the vector, looks good
for (int i=0; i<4; i++)
{
cout << x[i] << endl;
}
// refer fftw datatype to the std::vector by casting
fftw_complex* in = reinterpret_cast<fftw_complex*>(&x[0]);
// print in reference, gives random numbers
for (int i=0; i<4; i++)
{
cout << *in[i*2] << " " << *in[i*2+1] << endl;
}
}
But in seems not really pointing to the right place, it shows random numbers instead. Besides above question, my purpose is to generate a vector with 8 elements (example), the first 4 element refer to the std::vector but the last four is initialized as some constant. Is that possible to have *in pointing to the first in vector and then pointing to 4 constant values somewhere else, so I can fftw "in"? Thanks.
As said in http://www.fftw.org/fftw3_doc/Complex-numbers.html#Complex-numbers you must use reinterpret_cast to convert from double to fftw_complex. I guess this is one of the few cases that it is an adviced use.
It says too that fftw_complex is defined as:
typedef double fftw_complex[2];
so, the correct way to transverse you loop is by doing the following:
for (int i=0; i<4; i++)
{
fftw_complex* in = reinterpret_cast<fftw_complex*>(&x[i]);
cout << (*in)[0] << " " << (*in)[1] << endl;
}
UPDATE
You can also keep your in pointer definition as done before and interating you for loop doing this:
for (int i=0; i<4; i++)
{
cout << (in[i])[0] << " " << (in[i])[1] << endl;
}
First, never use reinterpret_cast because that can cause awful bugs.
Second, in defined as a complex number, a structure with 2 doubles. Therefore in[i*2] would access COMPLEX number indexed by i*2, consisting of doubles number (i*2)*2 and (i*2)*2+1 in the array. At i==1 you would actually output the 4th complex number, not the 2nd one, and at i==2 you would go out of bounds, causing either an invalid memory access crash or a garbage output.
Suppose you want to read the data from large text file (~300mb) to array of vectors: vector<string> *Data (assume that the number of columns is known).
//file is opened with ifstream; initial value of s is set up, etc...
Data = new vector<string>[col];
string u;
int i = 0;
do
{
istringstream iLine = istringstream(s);
i=0;
while(iLine >> u)
{
Data[i].push_back(u);
i++;
}
}
while(getline(file, s));
This code works fine for small files (<50mb) but memory usage is increasing exponentially when reading large file. I'm pretty sure that the problem is in creating istringstream objects each time in a loop. However, defining istringstream iLine; outside of both loops and putting each string into stream by iLine.str(s); and clearing the stream after inner while-loop (iLine.str(""); iLine.clear();) causes the same order of memory explosion as well.
The questions that arise:
why istringstream behaves this way;
if it is the intended behavior, how the above task can be accomplished?
Thank you
EDIT: In regards to the 1st answer I do clean the memory allocated by array later in the code:
for(long i=0;i<col;i++)
Data[i].clear();
delete []Data;
FULL COMPILE-READY CODE (add headers):
int _tmain(int argc, _TCHAR* argv[])
{
ofstream testfile;
testfile.open("testdata.txt");
srand(time(NULL));
for(int i = 1; i<1000000; i++)
{
for(int j=1; j<100; j++)
{
testfile << rand()%100 << " ";
}
testfile << endl;
}
testfile.close();
vector<string> *Data;
clock_t begin = clock();
ifstream file("testdata.txt");
string s;
getline(file,s);
istringstream iss = istringstream(s);
string nums;
int col=0;
while(iss >> nums)
{
col++;
}
cout << "Columns #: " << col << endl;
Data = new vector<string>[col];
string u;
int i = 0;
do
{
istringstream iLine = istringstream(s);
i=0;
while(iLine >> u)
{
Data[i].push_back(u);
i++;
}
}
while(getline(file, s));
cout << "Rows #: " << Data[0].size() << endl;
for(long i=0;i<col;i++)
Data[i].clear();
delete []Data;
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
cout << elapsed_secs << endl;
getchar();
return 0;
}
vector<> grows memory geometrically. A typical pattern would be that it doubles the capacity whenever it needs to grow. That may leave a lot of extra space allocated but unused, if your loop ends right after such a threshold. You could try calling shrink_to_fit() on each vector when you are done.
Additionally, memory allocated by the C++ allocators (or even plain malloc()) is often not returned to the OS, but left in a process-internal free memory pool. this may lead to further apparent growth. And it may cause the results of shrink_to_fit() to be invisible from outside the process.
Finally if you have lots of small strings ("2-digit numbers"), the overhead of a stringobject may be considerable. Even if the implementation uses a small-string optimization, I'd assume that a typical string uses no less than 16 or 24 bytes (size, capacity, data pointer or small string buffer) - probably more on a platform where size_type is 64 bits. That is a lot of memory for 3 bytes of payload.
So I assume you are seeing normal behaviour of vector<>
I seriously suspect this is not istringstream problem (especially, given you have same result with iLine constructor outside the loop).
Possibly, this is a normal behavior of the std::vector. To test that, how about you run the exact same lines, but comment out: Data[i].push_back(u);. See if your memory grows this way. If it doesn't then you know where the problem is..
Depends on your library, vector::push_back will expand its capacity by a factor of 1.5 (Microsoft) or 2 (glib) every time it needs more room.
So this is my main method:
#include <iostream>
#include "TextFileToArray.h"
#include <vector>
using namespace std;
int main()
{
cout << "Hello world!" << endl;
TextFileToArray myobject("C:/bunz.txt");
vector<string> v[10];
myobject.vectorfiller(*v);
for(int i =0; i<10; i++){
cout << v;
}
}
It calls upon an object known as myobject and it calls upon a method/function. Here is the method/function:
int TextFileToArray::vectorfiller(vector<string>& givenpointer) {
vector<string> *innervec = &givenpointer;
const char * constantcharversion = path.c_str();
ifstream filler(constantcharversion);
string bunz;
string lineoutliner = "Line ";
string equalssign = " = ";
int numbercounter = 1;
while (!filler.eof()) {
std::getline(filler, bunz, ';');
if (bunz.empty()) {
lineoutliner = "";
numbercounter = 0;
equalssign = "";
}
cout << lineoutliner << numbercounter << equalssign << bunz <<endl;
cout << "" << endl;
innervec->push_back(bunz);
numbercounter++;
}
filler.close();
return 0;
}
So far it displays the text from the textfile, but for some reason it pushes memory addresses into the vector, so when main() displays the vector, it shows memory locations:
vector<string> v[10]; creates an array of 10 vectors, which is probably not what you want.
Create a single vector, pass that as parameter, and output its contents:
vector<string> v;
myobject.vectorfiller(v);
for(int i =0; i < v.size(); i++){
cout << v[i];
}
Agree, size should not be 10, should be size(), and count<
The problem is that you're printing the array of vectors, not the elements in the first vector. Instead, you want this in your main:
for (int i = 0; i < v[0].size(); i++) {
cout << v[0][i] << endl;
}
PS: As Luchian said, you are creating 10 vectors, not one vector with 10 slots. To get just one vector do this:
vector<string> v;
You also don't need to mention 10; vectors grow when you push elements on them. If you happen to know how much space you want to be reserved ahead of time, you can use the reserve member function like so:
vector<string> v;
v.reserve(some_number);
reserve doesn't change the size of v; it only makes the vector ready to accept that many elements, so that it doesn't have to reallocate memory, and copy things around as much. It is purely an optimization; if you were to simply comment out reserve calls in your program, it will behave exactly the same. The only thing that might change is performance, and memory usage.