I'm semi new to c++. I have tried everything but couldn't solve my problem. Just for some background: I'm using the Botan library for encryption. I don't think this problem has anything to do with the library, but more with pointers and objects.
When I use the following code, there are no problems. The comments after each line explains what happens. (The code is for explanation purposes only)
int main(int argc, char** argv)
{
DH_PrivateKey *Apriv = 0; // Apriv points to 0x00
MemoryVector<unsigned char> *Apub = 0; // Irrelevant for now
AutoSeeded_RNG rng; // Irrelevant object
DL_Group domain("modp/ietf/3072"); // Irrelevant object
Apriv = new DH_PrivateKey(rng,domain); // Apriv points to 0x8079098
The main observation here is that an object is instantiated and Apriv points to that object. This is what I want to happen. The problem comes in when I try to do this in another function which I pass the Apriv pointer to.
My main code changes to the following:
int main(int argc, char** argv)
{
DH_PrivateKey *Apriv = 0;
MemoryVector<unsigned char> *Apub = 0;
AutoSeeded_RNG rng;
DL_Group domain("modp/ietf/3072");
encryption::dh_generatekeys("modp/ietf/3072",Apriv,Apub); //Passing pointers
And the function I pass these pointers to looks like this:
void encryptionalgorithm::dh_generatekeys(string shareddomain,DH_PrivateKey *privatekey,MemoryVector<unsigned char> *publickey)
{
AutoSeeded_RNG rng; // Irrelevant
DL_Group shared_domain(shareddomain); // Irrelevant
privatekey = new DH_PrivateKey(rng, shared_domain); //[PROBLEM 1]
MemoryVector<unsigned char> pubkey = privatekey->public_value();
publickey = &pubkey;[PROBLEM 2]
I will now describe the problems:
Problem 1: The privatekey pointer still points to 0x00, it does not point to the newly instantiated object, and this later causes segmentation errors.
Problem 2: The same with publickey, when I create "pubkey" on the stack and then point publickey pointer to its address, publickey just stays 0x00.
Any help would be appreciated. I hope it is something simple!
Thanks guys.
Your parameters are passed by value.
This means, if you modify the value of the pointer privatekey inside a function, you only modify a variable local to that function.
You might want to change your function signature to accept parameters as references instead:
void generatekeys(Something *& Apub, Something *& Apriv) { ... }
This reads right-to-left: Apub is a reference & to a pointer * to Something. Now any changes to Apub and Apriv inside generatekeys will propagate to the outside as you want, but note that you'll need to call that function passing proper variables (lvalues), not just some expressions (rvalues).
If in doubt, ask further or have a google for reference parameters.
Your problem is that dh_generatekeys takes both privatekey and publickey by value (that is the value of the pointer). Therefore what you modify are local copies of the pointers, instead of the pointers instead. The solution is simply to either pass a pointer or a reference to the pointer to your object, so:
void encryptionalgorithm::dh_generatekeys(string shareddomain,DH_PrivateKey** privatekey, MemoryVector<unsigned char>** publickey)
or
void encryptionalgorithm::dh_generatekeys(string shareddomain,DH_PrivateKey*& privatekey, MemoryVector<unsigned char>*& publickey)
If I understand correctly, yo ushould change dh_generatekeys to:
void encryptionalgorithm::dh_generatekeys(string shareddomain,DH_PrivateKey* &privatekey,MemoryVector<unsigned char>* &publickey) { ... }
That is to say use references to pointers. This way you can change them.
You need to pass the address of the pointers (or a reference) to be able to modify the value in the caller.
Address of pointer (pointer to pointer) example:
int main(int argc, char** argv)
{
DH_PrivateKey *Apriv = 0;
MemoryVector<unsigned char> *Apub = 0;
AutoSeeded_RNG rng;
DL_Group domain("modp/ietf/3072");
encryption::dh_generatekeys("modp/ietf/3072",&Apriv,&Apub); //Passing address of pointers
//...
}
void encryptionalgorithm::dh_generatekeys(string shareddomain,DH_PrivateKey **privatekey,MemoryVector<unsigned char> **publickey)
{
AutoSeeded_RNG rng; // Irrelevant
DL_Group shared_domain(shareddomain); // Irrelevant
*privatekey = new DH_PrivateKey(rng, shared_domain); //dereference to assign
MemoryVector<unsigned char> pubkey = privatekey->public_value();
*publickey = &pubkey; //dereference to assign
//...
}
Related
Under what circumstances might you want to use multiple indirection (that is, a chain of pointers as in Foo **) in C++?
Most common usage as #aku pointed out is to allow a change to a pointer parameter to be visible after the function returns.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
This will print
12
But there are several other useful usages as in the following example to iterate an array of strings and print them to the standard output.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
IMO most common usage is to pass reference to pointer variable
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
You can create multidimensional jagged array using double pointers:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
One common scenario is where you need to pass a null pointer to a function, and have it initialized within that function, and used outside the function. Without multplie indirection, the calling function would never have access to the initialized object.
Consider the following function:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Any function that calls 'initialize(foo*)' will not have access to the initialized instance of Foo, beacuse the pointer that's passed to this function is a copy. (The pointer is just an integer after all, and integers are passed by value.)
However, if the function was defined like this:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...and it was called like this...
Foo* my_foo;
initialize(&my_foo);
...then the caller would have access to the initialized instance, via 'my_foo' - because it's the address of the pointer that was passed to 'initialize'.
Of course, in my simplified example, the 'initialize' function could simply return the newly created instance via the return keyword, but that does not always suit - maybe the function needs to return something else.
If you pass a pointer in as output parameter, you might want to pass it as Foo** and set its value as *ppFoo = pSomeOtherFoo.
And from the algorithms-and-data-structures department, you can use that double indirection to update pointers, which can be faster than for instance swapping actual objects.
A simple example would be using int** foo_mat as a 2d array of integers.
Or you may also use pointers to pointers - lets say that you have a pointer void* foo and you have 2 different objects that have a reference to it with the following members: void** foo_pointer1 and void** foo_pointer2, by having a pointer to a pointer you can actually check whether *foo_pointer1 == NULL which indicates that foo is NULL. You wouldn't be able to check whether foo is NULL if foo_pointer1 was a regular pointer.
I hope that my explanation wasn't too messy :)
Carl: Your example should be:
*p = x;
(You have two stars.) :-)
In C, the idiom is absolutely required. Consider the problem in which you want a function to add a string (pure C, so a char *) to an array of pointers to char *. The function prototype requires three levels of indirection:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
We call it as follows:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
In C++ we have the option of using references instead, which would yield a different signature. But we still need the two levels of indirection you asked about in your original question:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Usually when you pass a pointer to a function as a return value:
ErrorCode AllocateObject (void **object);
where the function returns a success/failure error code and fills in the object parameter with a pointer to the new object:
*object = new Object;
This is used a lot in COM programming in Win32.
This is more of a C thing to do, in C++ you can often wrap this type of system into a class to make the code more readable.
I have an object named thingy with a method playWithString(char* text).
I have a character array such as
char testString = nullptr;
I want to pass testString into thingy.playWithString(char text)
I initially tried this by putting this at the start of the playWithString method
text = new char[128]
This works fine in the function, but once the function has ended testString is null again. How do I make it retain the value of the function result?
You need to pass by reference here. This is what is happening:
void playWithString (char* myptr) {
myPtr = new char [128];
//myPtr is a local variable and will not change the fact that testString still points to NULL
*myPtr = 'a';
*myPtr = 'b';
}
main () {
char *testString = NULL; //testString is not pointing to anything
playWithString(testString);
//tesString is still null here
}
To solve this: Pass by reference. Notice the & in signature of playWithString.
void playWithString (char* &myptr) {
myPtr = new char [128];
//myPtr is a local variable and will not change the fact that testString still points to NULL
*myPtr = 'a';
*myPtr = 'b';
}
main () {
char *testString = NULL; //testString is not pointing to anything
playWithString(testString);
//tesString is still null here
}
It sounds like you are attempting to modify the pointer, not the data to which the pointer is pointing. When you create a function, the parameters are ordinarily passed by value unless you make the parameter a pointer or a reference. This means that the parameters are copied and thus assignment to the parameter only modifies a copy, not the original object. In the case where the parameter is a pointer (array parameters are represented as a pointer to the first element in the array), the pointer is being copied (although the content to which it points is the same both outside and inside the function). With this pointer, you can modify the content to which it points and have the effect persist outside of the function; however, modifying the pointer itself (e.g. to make it point to a different array) is only modifying the copy; if you want such a mutation to last outside the function, you need an extra layer of indirection. In other words, you need to pass a pointer or reference to the pointer to be able to change its target.
P.S. As others have noted, for using strings, you really should use an std::string. That being said, it's good to understand the underlying mechanics and how to use char* when learning.
Maybe you should use c++ strings (std::string) ?
#include <string>
#include <iostream>
class A {
public:
void foo(const std::string& s) {
std::cout << s << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
std::string str = "Hello!";
a.foo(str);
return 0;
}
I encountered a problem.I try to change the pointer,but pointer does not change.
Here is my code:
void TestPoint(char* point)
{
point=new char[10];
}
int main(int argc, char* argv[])
{
char* test=NULL;
TestPoint(test);
**//At this point the "test" is still null,why ?**
return 0;
}
Sorry ,My english is very poor,and I don't know how to insert the c++ code.
Imagine you're going to the airport
You pick up a piece of paper and write down which terminal you need to go to, which flight and seat.
You call for a taxi to the airport. The taxi company asks you "Which terminal". You consult your piece of paper and tell them "Terminal 3". On the journey, you tell your driver you are flying to Paris and he tells you "Oh, you really want to go to Terminal 1, it'll be much faster".
You let him take you to Terminal 1. You make your flight, have a week in Paris and fly home. As you are unpacking, you find the original piece of paper.
Does it say Terminal 1 or Terminal 3?
This is an example of "pass by value" and in C and C++ pointers are actually variables much like any other. "Terminal 3" is a pointer, it is an address of a place at an airport. '0x073aff10' is a 32-bit integer value, but it could also be the address of the location in memory in which my credit card number is stored. If I tell you "Terminal 3" I am passing the address of the terminal I need by value.
This line of code:
void TestPoint(char* point)
Declares a function called "TestPoint". Whenever this function is invoked, the computer will reserve new storage for a "char*" pointer and you will be able to refer to that storage in code with the variable name "point". The storage will be on the stack, when you leave the function, the stack "unwinds" upwards, the variable is gone.
This line of code:
TestPoint(test);
Invokes the function test point, passing it the value of variable 'test'. What you see in TestPoint is not the same as 'test' its a copy of the value of test at the time you entered TestPoint.
Pointers are basically variables, like any other, with a slightly special contract that lets you do some extra magic with them - you and the computer agree that they are going to contain memory locations of things.
What you need is the address of the pointer itself:
TestPoint(&test)
and TestPoint needs to take a pointer-to-a-pointer-to-char
void TestPoint(char** point)
and in TestPoint you need to dereference "point" once to get to the pointer-to-char
*point = new char[10]
Alternatively, you could just make TestPoint take no argument and return a pointer value.
char* TestPoint()
{
char point = new char[10];
return point;
}
Try this, passing the address of the pointer,
void TestPoint(char** point)
{
*point=new char[10]; //assign to location at point
}
int main(int argc, char* argv[])
{
char* test=NULL;
TestPoint(&test);
printf("test: %x\n",test);
return 0;
}
A more C++ idiom would be to pass by reference,
void TestPoint(char* &point)
{
point=new char[10]; //assign to point reference
}
int main(int argc, char* argv[])
{
char* test=NULL;
TestPoint(test);
printf("test: %x\n",test);
return 0;
}
void TestPoint(char** point)
{
*point = new char[10];
}
int main(int argc, char* argv[])
{
char* test = NULL;
TestPoint(&test);
/******/
return 0;
}
That's because function TestPoint receives a copy of the test variable, modifies it (assigning pointer to allocated memory) and then discards. If you imagine replacing char* with, for instance, int, things may get clearer.
The very minimal change you can do is rewrite TestPoint signature in the following way
void TestPoint(char*& point)
thus passing test variable via reference. These online lessons may be of help. Chapters 7.2 - 7.4 are about passing arguments to function.
Class:
class myclass {
public:
myclass(void);
const char* server;
private:
char pidchar[6];
int pidnum;
};
The function
myclass parseINI(const char* file)
{
myclass iniOptions;
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(file);
const char* server = ini.GetValue("", "server", "");
iniOptions.server = server;
std::cout << server << "\n"; // Prints the correct value here
fflush(stdout);
return iniOptions;
}
Calling it from the main function
int _tmain(int argc, TCHAR* argv[])
{
myclass options;
options = parseINI("myapp.ini");
std::cout << options.server << "\n"; // It prints junk here
return 0;
}
What did I do wrong?
The const char* returned by GetValue() probably belonged to the ini object. When you exited the parseIni() function, ini went out of scope and was destroyed, which could mean your pointer is no longer valid.
Try using a std::string for the server member type instead of const char*.
It looks like you are using memory that is released when CSimpleIniA goes out of scope in parseINI.
const char* server = ini.GetValue("", "server", "");
iniOptions.server = server;
Copy the value that is returned into a new memory block before you return from the parseINI function.
string server = ini.GetValue("", "server", "");
iniOptions.server = new char[server.length() + 1];
std::copy(server.begin(), server.end(), iniOptions.server);
iniOptions.server[server.length()] = 0;
const char* server = ini.GetValue("", "server", "");
This value is falling out of scope when the function terminates, so when you assign the value of that pointer to your object's server pointer, the place in memory they point to is having its memory freed off the stack at the end of the function, and it's then overtaken by other things.
Using a std::string or even just a char[] will be preferred to just fix the problem with the least amount of changes, as they will by assigned the actual value and not a location in memory like pointers.
What you really should do is look up referential transparency, though. That will prevent problems like this from occurring ever again
I's guess that the lifetime of the data pointed to by the char* returned from CSimpleIniA::GetValue() is the same as the CSimpleIni object itself. So when ini is destructed, the pointer returned from GetValue() becomes invalid. (I've never used CSimpleIni, and haven't looked at the docs carefully enough to know for sure, but that's what the behavior points to).
I'd suggest changing myclass::server to be a std:string object and set it using something like:
iniOptions.server = std::string(server);
which will give the myclass::server object it's own copy of the string data.
The way you are using class as a function returned data type in C++ is totally wrong.
In C++ there are 2 kinds of data type: value type, reference type.
class belongs to second one; From a function you can return a value type data or a pointer of any data.But you cann't retun a entity of a reference type. Because a entity of a reference type will be released right after the code reached out of the scope which the entity is defined.
You can do in either way:
1:
define parseINI as:
myclass* parseINI(const char* file)
{
myclass* iniOptions = new myclass();
........
return iniOptions;
}
and then use it like this:
myclass* options = parseINI("myapp.ini");
2:
define parseINI as:
void parseINI(myclass& options, const char* file)
{
........//asigne value to options's members
}
and then use it like this:
myclass options;
parseINI(options,"myapp.ini");
3:
Do what you did, but add a asignment method (operator=) to myclass
The problem is that the local variable server points to a character buffer returned by ini.GetValue(), which is destroyed when paraseINI() returns.
One way to fix this is to allocate a new buffer yourself and copy the characters.
const char* server = ini.GetValue("", "server", "");
int length = strlen(server) + 1; // length of the string +1 for the NULL character.
delete [] iniOptions.server; // free the old buffer
iniOptions.server = new char[length]; // allocate your own buffer
strncpy(iniOptions.server, server, length); // copy the characters
For this to work you have to make myclass::server non-const, and you have to initialize it to NULL in the constructor and delete it in the destructor.
A better way to deal with this situation would be use std::string instead of char * for muclass::server. This way std::string would take care of memory management for you, and the code would be exception-safe.
If you make muclass::server an std::string, then you simply do
const char* server = ini.GetValue("", "server", "");
iniOptions.server = std::string(server);
And you do not have to do anything with it in the constructor or the destructor.
iniOptions is located on the stack and disposed automatically when the function returns. You should allocate it on heap using new()
Under what circumstances might you want to use multiple indirection (that is, a chain of pointers as in Foo **) in C++?
Most common usage as #aku pointed out is to allow a change to a pointer parameter to be visible after the function returns.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
This will print
12
But there are several other useful usages as in the following example to iterate an array of strings and print them to the standard output.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
IMO most common usage is to pass reference to pointer variable
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
You can create multidimensional jagged array using double pointers:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
One common scenario is where you need to pass a null pointer to a function, and have it initialized within that function, and used outside the function. Without multplie indirection, the calling function would never have access to the initialized object.
Consider the following function:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Any function that calls 'initialize(foo*)' will not have access to the initialized instance of Foo, beacuse the pointer that's passed to this function is a copy. (The pointer is just an integer after all, and integers are passed by value.)
However, if the function was defined like this:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...and it was called like this...
Foo* my_foo;
initialize(&my_foo);
...then the caller would have access to the initialized instance, via 'my_foo' - because it's the address of the pointer that was passed to 'initialize'.
Of course, in my simplified example, the 'initialize' function could simply return the newly created instance via the return keyword, but that does not always suit - maybe the function needs to return something else.
If you pass a pointer in as output parameter, you might want to pass it as Foo** and set its value as *ppFoo = pSomeOtherFoo.
And from the algorithms-and-data-structures department, you can use that double indirection to update pointers, which can be faster than for instance swapping actual objects.
A simple example would be using int** foo_mat as a 2d array of integers.
Or you may also use pointers to pointers - lets say that you have a pointer void* foo and you have 2 different objects that have a reference to it with the following members: void** foo_pointer1 and void** foo_pointer2, by having a pointer to a pointer you can actually check whether *foo_pointer1 == NULL which indicates that foo is NULL. You wouldn't be able to check whether foo is NULL if foo_pointer1 was a regular pointer.
I hope that my explanation wasn't too messy :)
Carl: Your example should be:
*p = x;
(You have two stars.) :-)
In C, the idiom is absolutely required. Consider the problem in which you want a function to add a string (pure C, so a char *) to an array of pointers to char *. The function prototype requires three levels of indirection:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
We call it as follows:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
In C++ we have the option of using references instead, which would yield a different signature. But we still need the two levels of indirection you asked about in your original question:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Usually when you pass a pointer to a function as a return value:
ErrorCode AllocateObject (void **object);
where the function returns a success/failure error code and fills in the object parameter with a pointer to the new object:
*object = new Object;
This is used a lot in COM programming in Win32.
This is more of a C thing to do, in C++ you can often wrap this type of system into a class to make the code more readable.