I am writng a c++ program. I am parsing a file and initializing a structure. I have an array to initialize but I have to read the size of the array from the file. I want the array length read and array initialization in one function. If I pass the array pointer to another function and do a new, when the function returns, the pointer is destroyed, and I cannot see the initialized values. Is this expected or am I missing something. How can I overcome this problem?
You overcome this by forgetting everything about manual arrays, raw pointer passing* and new. This is C++, not 1991. So, a typical solution could be this:
#include <vector>
#include <cstdint>
#include <istream>
std::vector<uint32_t> read_data(std::istream & is)
{
uint32_t len;
is.read(reinterpret_cast<char*>(&len), sizeof(uint32_t));
std::vector<uint32_t> result(len);
for (uint32_t i = 0; i != len; ++i)
{
is.read(reinterpret_cast<char*>(&result[i]), sizeof(uint32_t));
}
return result;
}
(In high-quality code, the read commands would be surrounded by a conditional and errors would be handled, possibly by throwing an exception.)
Later:
#include "int_reader.hpp"
#include <fstream>
#include <iostream>
int main()
{
std::ifstream infile("thedata.bin", std::ios::binary);
std::vector<uint32_t> data = read_data(infile);
std::cout << "We read " << data.size() << " integers.\n";
}
*) The only raw pointer that has a place in general-purpose C++ is a char* when used for I/O operations, as demonstrated by this code. C++ defined char to be the machine's fundamental data unit type, and I/O happens in units of char.
There is no array pointer before you call new. So there's no way you could pass it to a function.
Likely what you're doing is passing the uninitialized, garbage value of the array pointer to a function. The function overwrites its copy of that garbage value with the correct pointer returned from new, but then the original function never sees that pointer.
You need to pass the function a pointer to the pointer. Then when it calls new, it can use the pointer to the pointer to update the caller's pointer. Like this:
void SomeFunction(void **SomePointer)
{
(*SomePointer) = malloc(1024);
}
void *MyPointer;
SomeFunction(&MyPointer);
You have to pass a pointer to a pointer in order to have a function allocate it for you
void allocateArrayOfT(T** objArray, size_t len) {
*objArray = new T[len];
}
You can call:
T* arrayPtr;
allocateArrayOfT(&arrayPtr, len);
Related
In order to understand how void pointer works, I wrote a piece of code to test it. However I got the segmentation fault during the runtime and had not clue how to deal with it. The key point here is that, the data are generated inside that function call. You don't know the datatype and how large is that void pointer should be allocated.
#include <iostream>
#include <vector>
int valueAssignment(void *ptr1, void *ptr2){
std::vector<int> vi;
std::vector<double> vb;
int num = 10;
for (size_t i = 0; i < num; i++) {
vi.push_back((int)rand());
vb.push_back((double)rand());
std::cerr <<i<<": "<< vi[i] <<'\t'<<vb[i]<<'\n';
}
for (size_t i = 0; i < num; i++) ((int*)ptr1)[i] = vi[i];
for (size_t i = 0; i < num; i++) ((double*) ptr2)[i] = vb[i];
return num;
}
int main(int argc, char const *argv[]) {
void * intPtr, *doublePtr;
int size;
size = valueAssignment(intPtr,doublePtr);
std::cerr << "/* ------------------- */" << '\n';
for (size_t i = 0; i < size; i++) {
std::cout <<i<<": "<< ((int*)intPtr)[i]<<"," <<((double *)doublePtr)[i]<<std::endl;
}
return 0;
}
We should simply follow the many many recommendations given by experts.
Do not use raw pointers in C++
Do not use raw pointers in C++
Do not use raw pointers in C++
WIth that we woulld already make a huge progress. But then, you want to learn about a void* pointer. The void pointer is a somehow generic pointer that can point to anything. You can also assign other pointer types to a void pointer. Vice versa this is not possible and you need an explicit type cast.
With classes and espcially derived classes you may even lose information by doing such casts.
Legacy C codes often uses void pointers, but that is basically no problem.
In modern C++, void pointers are rarely needed. Maybe mainly to interface with legacy code.
So, now to your special case:
The problem has been mentioned already in many comments. And this has nothing to do with void pointers, but pointers in general. Your pointers are not initialized. They point to somewhere, randomly at some point in memory. And in your subfunction, you are assigning values to those none initalized pointers, writing values to somewhere randomly in memory. Your program will chrash.
So, a pointer needs to point to somewhere defined. To a defined memory region.
You could have written:
int intArray10[10]; // You should not use C-Style plain arrays
double doubleArray10[10]; // You should not use C-Style plain arrays
void* intPtr = intArray10;
void* doublePtr = doubleArray10;
Then your pointer would point to a defined region. And you program would work.
But then you want to define or use somehow the pointer within your function. If the size is known, then you can allocate data with new and assign it to the pointer. The pointer must then be passed as "reference to pointer" or "pointer to pointer". If the size is unknown, it will be more difficult, you need to inform the calling program on the size.
All this is very error prone and should be avoided.
So again: Do not use raw pointer. If you really need them for some ressource management, then use std::unique_ptr or std::shared_ptr.
Or better use STL container in the first place.
I have an Eigen matrix to be converted to a C array. I can replicate the issue with the following example.
#include <iostream>
#include <Eigen/Core>
int *test()
{
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
// just to check
arr(4)=3;
arr(5)=19;
return arr.data();
}
int main()
{
int *c_arr;
c_arr = test();
for (int i=0; i<6;++i)
{
std::cout << c_arr[i] << std::endl;
}
return 0;
}
Output:
0
0
1
1
3
19
Now if I print the converted C array values from within the test function the values are correct. However if I print the values from main (as shown above) the first two indices are always garbage. So I am wondering what is happening in the function call? I have tried this with different Eigen matrices (types, sizes) and I get the same result.
I'll start by saying I'm not 100% familiar with the Eigen library (just downloaded it to look at it out of curiosity) and it's documentation is a bit lacking but your problem is a fundamental C problem that can be remedied a few ways.
First we'll start by explaining what's happening in your code to give garbage values:
int *test()
{
/* create an auto scoped variable on the stack;
this variable is only "visible" to this function
and any references to it or it's underlying data
outside the scope of this function will result
in "undefined behaviour" */
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
arr(4)=3;
arr(5)=19;
/* arr.data() is defined as returning a pointer to the scalar underlying type (or
a C-style array in other words). Regardless of the type being returned, it is pointer based
and you are returning a pointer to a location in memory, not the actual data being held in
the memory. */
return arr.data();
} /* the variable arr is destroyed here since we left function scope and the return value (the pointer location)
is put in the return register and "program flow" is returned back to the main function where the pointer being
returned now points to "invalid" memory */
int main()
{
int *c_arr; // create a pointer type that can reference int types
c_arr = test(); // point it to the result of the test function (see notes above)
/* c_arr now points to a memory location returned from test, but since the
arr variable no longer exists here, when you go through and print the values pointed
to at those memory locations you will get what is at those locations and could be "anything"
except a valid reference to the original arr variable and it's underlying data. */
for (int i=0; i<6;++i)
{
std::cout << c_arr[i] << std::endl;
}
return 0;
}
So that's the why, as for how to fix it there are a couple of ways to go about your problem; one is to pass the return array in as a variable in to your test function (e.g. void test(int*& val)), you could then choose to allocate new memory to the variable in the test function, or assume the user has already done so, and must also assume the user will clean up after themselves and call delete[] (not just delete since you're operating on arrays of data).
But this has many caveats of needing to know how much space to allocate and being sure to deallocate when done. I'm not sure why you specifically need a C-style array but since you're using C++, it might be more prudent if you use some of the STL and container functions available to you to help you out, example:
#include <iostream>
#include <vector>
#include <Eigen/Core>
std::vector<int> test()
{
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
arr(4)=3;
arr(5)=19;
// we need the size so we know how big of a container to allocate
std::size_t sz = arr.innerSize() * arr.outerSize();
std::vector<int> ret(sz);
// get a temporary C array pointer so we can reference the data
int* tmp = arr.data();
// copy from tmp[0] to tmp[sz] and insert the data into the first element of ret
std::copy(tmp, tmp+sz, ret.begin());
// return the (copied) data
return ret;
}
int main()
{
std::vector<int> c_arr = test();
// c_arr now points to valid data it holds and can be iterated on
for (std::size_t i = 0; i < c_arr.size(); ++i) {
std::cout << c_arr[i] << std::endl;
}
// if you need a C-style array from here, you can easily copy the data
// from the vector to your C-array
return 0;
}
I looked into using the cast() function of the class, but could not quite figure out the syntax to make it less painful than just copying it the above way since it looks like you'd have to call the cast function to a differnt Eigen type and then cast again from there, but know there is a cast function and other methods to get the underlying data of the MatrixX classes if you need access to it.
I hope that can help.
Syntax for std::fread :
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
we can call std::fread with a character pointer and get the read data with the same character pointer.
eg:
char* data;
fread(data,5,10,file);
What i tried is to create a similar function which accepts a character pointer as a void* pointer.
#include <iostream>
#include<string.h>
using namespace std;
void modify(void* ptr)
{
char* temp = new char[50];
strcpy(temp,"testing");
__ptr=(void*)temp;
std::cout<<"__ptr="<<(char*)__ptr<<endl;
}
int main()
{
char* str;
modify(str);
cout<<"str="<<str;
return 0;
}
I tried the above code with http://www.compileonline.com/compile_cpp11_online.php and I got the output as
__ptr=testing
str=
(a)Why str is not printing the string "testing"?
I am assigning the address of a dynamically allocated variable to ptr.
So the value "testing" must be available in the heap even after the control returns from the method.
(b)How can i modify the function so that i will get the output as
__ptr=testing
str=testing
But function prototype cannot be modified.
Please help.
Hope the question is clear.
The problem is that the function modify() takes a reference to a void* but you are actually passing a char*. This is not valid C++ and should not compile.
That said, there are some old C++ compilers out there (Visual C++ 6?) that have a kind of extension, that allows you to do that. That is when you are calling modify(str), the compiler is creating a temporary value of type void* and initializing it to the value of str. Then the temporary is passed to the function and taking the address of the allocated memory. But, obviously, the str original value is never modified, so it remains uninitialized.
That's the main reason why the original C++ rule forbidding this is there: to protect you from this kind of bugs.
You have two solutions:
Declare the function with the proper pointer type: void modify(char*& ptr).
Change the compiler!
If you really wanted the function as is you could call it with modify(reinterpret_cast<void*&>(str)) but I do not recommend that!
By the way, never name your identifier with two underscores (__ptr) these names are reserved for the compiler writers only·
Ah! I understand now the OP problem: his idea is to write a wrapper to fread that allocates memory, reads into it from a file and returns the pointer. It is easier if you just return the pointer the usual way. Using your modify() simplified example:
void* modify()
{
char* temp = new char[50];
strcpy(temp,"testing");
return temp;
}
And then, to call it:
char *ptr = static_cast<char*>(modify());
From the valuable answer and comments from #rodrigo, i was able to solve my problem.
I modified the function.
void modify(void* ptr)
{
char* temp;
temp = (char *)ptr;
strcpy(temp,"testing");
}
This solved all the issues!
Like following code:
#include <iostream>
#include <string>
#define BUF_LEN_HEAP 32
#define BUF_LEN_STACK 64
int getBufLen(const char *buf)
{
//...
}
void foo(const char *buf)
{
int len = getBufLen(buf);
//memcpy(new_buf, buf, len);
//...
}
int main()
{
char buf_stack[BUF_LEN_STACK];
char *buf_heap = new char[BUF_LEN_HEAP];
std::string str("abcdef");
foo(buf_stack);
foo(buf_heap);
foo(str.c_str());
delete [] buf_heap;
return 0;
}
If get length of buffer very difficult pass argument to the functions.
Is there lower-level method to get length of buffer whatever the buffer allocated on stack or heap?
No, there is no way to get the size of an array outside of the method that declared it, and only if the array was declared with a static length (known at compile time).
The usual way to handle this is to pass both a pointer and a size to any function writing to the buffer, just as memcpy does.
With c++ there's always the better option to use a std::vector instead of a plain array. The std::vector carries all needed information within one object that's easy to pass around.
I have a C++ function which returns a std::vector<float>.
I am interfacing with some C code.
How do I change this C++ function so that it returns some pointer to a float array, and how do I save this returned array so that I can use it in my C code?
You can get a pointer to a "raw" array with std::vector::data or &my_vector[0] if C++11 is not available. However, if a vector operation forces the vector to be resized then the raw storage will move around in memory and this pointer will no longer be safe to use. If there is any possibility of this happening, you will need to allocate separate storage (e.g. by creating a copy of the vector) and provide a pointer to that instead.
Update: Woodrow's comment made me notice that you are actually after returning a pointer from a function. You can only return pointers to heap-allocated memory, so you cannot use a local vector (or any other type of stack-allocated memory) to do this.
From a C point of view, vector<float> does two things:
Contain some floats
Automatically free the memory it uses
Since 2 is an alien concept to C (nothing much happens automatically, certainly not freeing memory), there's no simple replacement. Basically you have three options. They are the same as the three options you have when you want functions to "return strings" in C, although here we need to tell the caller both a pointer and a length.
In my opinion, the third option is "the right answer", in the sense that it's the one you try first in your design, and if the design looks OK you stick with it. The first and second can be provided as convenience functions in cases where the calling code will really benefit from them, either wrapped around or alongside the third.
Return allocated memory
size_t c_wrapper(float **pResult) {
try {
std::vector<float> vec(cpp_function());
*pResult= (float*) std::malloc(vec.size() * sizeof(float));
if (!*pResult) { /* handle the error somehow */ }
std::copy(vec.begin(), vec.end(), *pResult);
return vec.size();
} catch (std::bad_alloc) { /* handle the error somehow */ }
}
Upside: Simple calling code.
Downside: The caller has to free the memory, even if the size is known in advance and the data would happily fit in a local array variable. Might be slow due to memory allocation.
Model: strdup (Posix)
Use shared static-duration resources
See jrok's answer:
size_t c_wrapper(float **pResult) {
try {
static std::vector<float> vec;
vec = cpp_function(); // or cpp_function().swap(vec) in C++03
*pResult = &vec[0];
return vec.size();
} catch (std::bad_alloc) { /* handle the error somehow */ }
}
Upside: Ridiculously simple calling code.
Downside: There is only one instance of save in the program, so the returned pointer only points to the correct data until the next time c_wrapper is called. In particular, this is very thread-unsafe. If the result is very large, then that memory is wasted from the time the caller no longer needs it until the time the function is next called.
Model: strtok, gethostbyname.
Write the data into a buffer provided by the caller
size_t c_wrapper(float *buf, size_t len) {
try {
std::vector<float> vec(cpp_function());
if (vec.size() <= len) {
std::copy(vec.begin(), vec.end(), buf);
}
return vec.size()
} catch (std::bad_alloc) { /* handle the error somehow */ }
}
Upside: Most flexible.
Downside: The caller has to pass in a big enough buffer (assuming cpp_function behaves consistently, caller can find out the size by calling the function with size 0 and a null pointer, get a big enough buffer from somewhere, then call the function again).
Model: strcpy, snprintf, getaddrinfo.
You could save the returned temporary vector in a vector object with static storage duration.
std::vector<float> foo()
{
return std::vector<float>();
}
float* call_foo_and_get_pointer()
{
static std::vector<float> save; // this line is executed only at the first
// call to enclosing function
save = foo();
return save.data(); // or &data[0]
}
The pointer returned from call_foo_and_get_pointer is guaranteed to stay valid until the next call to it.
#include <vector>
#include <iostream>
int main()
{
std::vector<float> vec;
vec.push_back(1.23);
vec.push_back(3.123);
int len = vec.size();
float *arr = new float[len];
std::copy(vec.begin(),vec.end(),arr);
for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i){
std::cout << arr[i] << "\n";
}
delete [] arr;
return 0;
}