Consecutive lines printing same pointer with "std::cout" produce completely different output - c++

I apologize for the vague title of my question. I don't know a better way to phrase it. I've never asked a Stack Overflow question before but this one has me completely stumped.
A method in class Chunk uses the Eigen linear algebra library to produce a vector3f, which is then mapped to a C-style array with the following.
ColPivHouseholderQR<MatrixXf> dec(f);
Vector3f x = dec.solve(b);
float *fit = x.data();
return fit;
This array is returned and accessed in the main function. However, whenever I attempt to print out a value from the pointer, I get completely different results. A sample is below.
Chunk test = Chunk(CHUNK_SIZE, 0, 0, 1, poBand);
float* fit = test.vector; // Should have size 3
std::cout << fit[0] << std::endl; // Outputs 3.05 (correct)
std::cout << fit[0] << std::endl; // Outputs 5.395e-43
std::cout << fit[0] << std::endl; // Outputs 3.81993e+08
What makes this issue even more perplexing is that the incorrect values change when I end the lines with "\n" or ", ". The first value is always the expected value, no matter whether I print index 0, 1, or 2.
I have tried dynamically allocating memory for the fit variable, as well as implementing the code on this answer, but none of it changes this functionality.
Thank you in advance for any guidance on this issue.
Minimally Reproducible Example:
float* getVector() {
Eigen::Vector3f x;
x << 3, 5, 9;
float* fit = x.data();
return fit;
}
int main(void) {
float* fit = getVector();
std::cout << fit[0] << std::endl;
std::cout << fit[0] << std::endl;
std::cout << fit[0] << std::endl;
}

You create the vector x in the function on the stack. It is destroyed after the function exited. Hence your pointer is invalid.
Here an example with shared_ptr
ColPivHouseholderQR<MatrixXf> dec(f);
Vector3f x = dec.solve(b);
shared_ptr<float> fit(new float[3],std::default_delete<float[]>());
memcpy(fit,x.data(),sizeof(float)*3);
return fit;
Another possible way is
ColPivHouseholderQR<MatrixXf> dec(f);
Vector3f x = dec.solve(b);
return x;

Related

Why is Eigen not making a copy when I return by value if copy elision is deactivated?

I currently have the very simple program. I deactivated copy elision in my compiler and as far as I understand it shouldn't even apply here because the compiler doesn't know what I will input. Now, the very weird thing is that when I look at the addresses they match what I would expect if no copy was happening with the value that is returned by the function. However, THERE is a copy happening when I say Eigen::MatrixXf m2 = m. I have no idea why the adresses match as inutitively I expect there to be a copy.
#include <iostream>
#include <Eigen/Dense>
Eigen::MatrixXf no_copy(){
Eigen::MatrixXf m = Eigen::MatrixXf::Random(3,3);
Eigen::MatrixXf m2 = Eigen::MatrixXf::Random(3,3);
int c = 0;
std::cin >> c;
std::cout << "m" << &m(0,0) << std::endl;
std::cout << "m2" << &m2(0,0) << std::endl;
if (c > 0) {
std::cout << "m " << std::endl;
return m;
}
else{
std::cout << "m2 " << std::endl;
return m2;
}
return m;
}
int main() {
//make a 1000 x 1000 matrix of random floats
Eigen::MatrixXf m;
m = no_copy();
Eigen::MatrixXf m2 = m;
std::cout << m << std::endl;
std::cout << &m(0,0) << std::endl;
std::cout << &m2(0,0) << std::endl;
return 0;
}
`
I tried doing Eigen::MatrixXf m2 = std::move(m); to see if a move was the reason for the odd behavior, but I got an assertion error when I tried it. Why isn't Eigen copying the matrix that is returned in the no_copy function?
Eigen::MatrixXf holds a matrix of a dynamically chosen size. Therefore it can't be storing the matrix elements directly inside its own storage. It must be using a dynamic allocation, the same way that std::vector does.
return m;, if NRVO is not applied, will use the move constructor to construct the temporary result object of the function call and m = no_copy(); will also use the move assignment operator to assign from this temporary. If the move operations are implemented properly, they will not do any additional allocation, but instead just take over ownership of the dynamic allocation that the original MatrixXf made.
You are printing addresses into the dynamic allocation, which shouldn't have changed.
Eigen::MatrixXf m2 = m; is copy-construction, not move-construction, so it can't do the same. It needs to make a new dynamic allocation and copy over the values. The addresses must be different. Copy elision is also impossible.
Eigen::MatrixXf m2 = std::move(m); results in an error because you are still trying to index into m afterwards although you have moved from it and its dynamic allocation isn't owned by m anymore.

What is the relationship between an array and its address?

The following code:
#include<iostream>
int main (void) {
int lista[5] = {0,1,2,3,4};
std::cout << lista << std::endl;
std::cout << &lista << std::endl;
std::cout << lista+1 << std::endl;
std::cout << &lista+1 << std::endl;
std::cout << lista+2 << std::endl;
std::cout << &lista+2 << std::endl;
std::cout << lista+3 << std::endl;
std::cout << &lista+3 << std::endl;
return (0);
}
Outputs:
0x22ff20
0x22ff20
0x22ff24
0x22ff34
0x22ff28
0x22ff48
0x22ff2c
0x22ff5c
I understood that an array is another form to express a pointer, but we cannot change its address to point anywhere else after declaration. I also understood that an array has its value as the first position in memory. Therefore, 0x22ff20 in this example is the location of the array's starting position and the first variable is stored there.
What I did not understand is: why the other variables are not stored in sequence with the array address? I mean, why lista+1 is different from &lista+1. Should not they be the same?
In pointer arithmetic, types matter.
It's true that the value is the same for both lista and &lista, their types are different: lista (in the expression used in cout call) has type int* whereas &lista has type int (*)[5].
So when you add 1 to lista, it points to the "next" int. But &lista + 1 points to the location after 5 int's (which may not be a valid).
Answering the question as asked:
std::cout << &lista+1 << std::endl;
In this code you take the address of array lista and add 1 to obtained answer. Given the sizeof of the array is sizeof(int) * 5, which means when you increment a pointer to it by 1 you add sizeof(int) * 5 to the pointer address, you end up with a number you see.

Simulate std::vector with mixed const and non-const elements

I'd like to simulate a std::vector that has mixed const and non-const elements. More specifically, I want to have functions that operate on a vector and are allowed to see the entire vector but may only write to specific elements. The elements that can and cannot be written will be determined at runtime and may change during runtime.
One solution is to create a container that holds an array of elements and an equal sized array of booleans. All non-const access would be through a function that checks against the boolean array if the write is valid and throws an exception otherwise. This has the downside of adding a conditional to every write.
A second solution might be to have the same container but this time write access is done by passing an array editing function to a member function of the container. The container member function would let the array editing function go at the array and then check that it didn't write to the non-writable elements. This has the downside that the array editing function could be sneaky and pass around non-const pointers to the array elements, let the container function check that all is well, and then write to non-writable elements.
The last issue seems difficult to solve. It seems like offering direct writable access ever means we have to assume direct writable access always.
Are there better solutions?
EDIT: Ben's comment has a good point I should have addressed in the question: why not a vector of const and a vector of non-const?
The issue is that the scenario I have in mind is that we have elements that are conceptually part of one single array. Their placement in that array is meaningful. To use vectors of const and non-const requires mapping the single array that exist in concept to the two vectors that would implement it. Also, if the list of writable elements changes then the elements or pointers in the two vectors would need to be moved about.
I think you can accomplish what you wish with the following class, which is very simplified to illustrate the main concept.
template <typename T>
struct Container
{
void push_back(bool isconst, T const& item)
{
data.push_back(std::make_pair(isconst, item));
}
T& at(size_t index)
{
// Check whether the object at the index is const.
if ( data[index].first )
{
throw std::runtime_error("Trying to access a const-member");
}
return data[index].second;
}
T const& at(size_t index) const
{
return data[index].second;
}
T const& at(size_t index, int dummy) // Without dummy, can't differentiate
// between the two functions.
{
return data[index].second;
}
T const& at(size_t index, int dummy) const // Without dummy, can't differentiate
// between the two functions.
{
return data[index].second;
}
std::vector<std::pair<bool, T> > data;
};
Here's a test program and its output.
#include <stdio.h>
#include <iostream>
#include <utility>
#include <stdexcept>
#include <vector>
//--------------------------------
// Put the class definition here.
//--------------------------------
int main()
{
Container<int> c;
c.push_back(true, 10);
c.push_back(false, 20);
try
{
int value = c.at(0); // Show throw exception.
}
catch (...)
{
std::cout << "Expected to see this.\n";
}
int value = c.at(0, 1); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = c.at(1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
value = c.at(1, 1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
// Accessing the data through a const object.
// All functions should work since they are returning
// const&.
Container<int> const& cref = c;
value = cref.at(0); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = cref.at(0, 1); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = cref.at(1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
value = cref.at(1, 1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
// Changing values ... should only work for '1'
try
{
c.at(0) = 100; // Show throw exception.
}
catch (...)
{
std::cout << "Expected to see this.\n";
}
c.at(1) = 200; // Should work.
std::cout << "Got c[1]: " << c.at(1) << "\n";
}
Output from running the program:
Expected to see this.
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Got c[0]: 10
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Expected to see this.
Got c[1]: 200

std::cout prevents a segfault in function?

I'm using the finite element library for some calculations, and I've encountered a bizarre problem.
I basically have the following for loop:
MeshBase::const_node_iterator node_it = mesh.nodes_begin();
for (unsigned int i=0;i<n_nodes;i++ , node_it++){
const Node* node2 = *node_it;
Point dumpoint( (*node2)(0), (*node2)(1), (*node2)(2));
Number dumreal= (Number) mesh_data.get_data(node2)[0];
// std::cout << dumreal <<std::endl;
dummap[dumpoint] = mesh_data.get_data(node2)[0];
}
If I uncomment the line with cout, it works. Otherwise I get a segfault. It doesn't matter what I print:
std::cout << std::endl;
An important note is that dummap is a global
std::map<Point,Number>
Using valgrind showed that the problem was with some char* array I allocated somewhere else.
Thanks ^^

Creating a 1D Vector and Assigning Values by Reference C++

I'm a novice coder, just a few months into learning C++. This is my second question on Stack Overflow, and I really hope that the answers will benefit me and others.
I started working on this program because I wanted to create a vector engine that could create a 1D vector, assign a value to any position in that 1D vector (by abstracting width and height to simulate 2D), and then print out said vector. The end goal of a project like this would be to later have a rendering engine that would convert the int values in this vector to image tiles on the screen using SDL or equivalent.
I previously made a program that could do something similar using a vector of objects each containing a character, but I didn't pass values by reference, so I really wanted to nail passing values by reference in this program.
The code compiles just fine, and the cout statements in the assignToVector function seem to indicate that the value is being assigned properly. But when I call the final print statement, the value that I want to pass into the vector is not properly outputted. I'm using vector.erase to clear the position before assigning a value to it, and vector.assign to input the value, if that helps narrow down the problem.
I really appreciate the time anyone spends answering this question! Thank you!
EDIT: The suggestion made by chris below fixed the first part of the problem (change
std::cout << printerVector[*it] TO std::cout << *it).
However I find I needed to add a position--; after I create it in order to align the value
properly. Basically, the inputted width and height values don't match their actual position on the grid. Any further help on this would be appreciated! I think it's an issue related to one dimensional vectors and using them as 2D.
//The purpose of this program is to create a one dimensional vector of integers
//that is equal to the desired screen size. Look at the preprocessor defines
//to change these values.
//The program also contains a function to print the created vector for testing
//purposes.
#include <iostream> //Needed for std::cout and std::endl
#include <vector> //Needed for std::vector and others
#define CONSOLEWIDTH 80;
#define CONSOLEHEIGHT 25;
//This function is supposed to assign a value to a specific point in the 1D vector matrix.
//The posWidth and posHeight are used to compute the location with default console values, mimicking 2D.
void assignToVector(std::vector<int>& intVector, int posWidth, int posHeight, int assignValue);
//This is mostly just a testing function to ensure that the desired
//contents are properly stored in the vector.
void printVector(std::vector<int>& printerVector);
//Creates the test vector, prints it, modifies it, and prints it again
void setupAndRun();
int main()
{
setupAndRun();
}
void assignToVector(std::vector<int>& intVector, int posWidth, int posHeight, int assignValue)
{
int position = posWidth + posHeight*CONSOLEWIDTH;
//std::cout << intVector[position] << std::endl;
std::cout << position << std::endl;
intVector.erase(intVector.begin() + position);
//std::cout << intVector[position] << std::endl;
std::cout << assignValue << std::endl;
intVector.insert(intVector.begin() + position, 1, assignValue);
std::cout << intVector[position] << std::endl;
}
void printVector(std::vector<int>& printerVector)
{
for(std::vector<int>::iterator it = printerVector.begin(); it != printerVector.end(); it++)
{
std::cout << printerVector[*it];
}
}
void setupAndRun()
{
int width = CONSOLEWIDTH;
int height = CONSOLEHEIGHT;
//Creates a vector of size argument1 that each have a value of argument2
//This syntax doesn't seem to work inside classes
std::vector<int> testVector(width*height, 8);
//80*25 8's
printVector(testVector);
//Suppossed to assign 200 to the 10th position of the first row of testVector
assignToVector(testVector, 10, 0, 200);
//Prints out 200
std::cout << testVector[10] << std::endl;
//Prints out default value
std::cout << testVector[9] << std::endl;
//Doesn't have a 200 in it
printVector(testVector);
}