Since in C++, NULL is essential jus 0. Every time I have a variable uninitialized set to NULL and later on I want to check whether this variable is initialized or not by comparing it to NULL. However, if the variable happens to be assigned to 0 somewhere, then there is no way I can tell whether it has been initialized or not. There is definitely some work around I can do to avoid the situation like using another wrapped object to wrap the variable or use a flag. But I am looking for a more elegant solution. For example:
int b[4] = {1,2,3,0};
int a = NULL;
int i = 0;
while(true){
if(a == 0)return;
a = b[i++];
}
so here it will goes into the if statement right away but I want to wait
until a is assigned to 0 by b's last element
I think what you're looking for is boost::optional.
#include <boost/optional.hpp>
...
boost::optional<int> maybe_int;
...
if (maybe_int) // test if it has been assigned to
{
if (maybe_int.value() == 0) // has is been set to zero?
{
// ...
}
}
I think you're making a conceptual mistake here. Even though NULL is defined as 0 somewhere, this does not mean they are the same on a conceptual level.
NULL is a pointer with (usually) the value 0. By convention, there cannot be an object at NULL. We can therefore use code such as MyClass *obj = NULL; to specify that there is no object at obj. This works because obj is a pointer.
For non-pointer types, this does not work and we need to use other tools such as arbitrarily defining one value as invalid (often -1is used for this) or using optionals.
Related
I'm having a hard time figuring out why the initialisation at NULL of one pointer is bugging my program.
In order to not receive a compilation error, almost all the pointers in my code need to be initialise as nullptr like usual. Problem is, when I tried to use them afterwards, I get a whole bunch of errors telling me the null pointer is invalid. To overcome this error, the buggy pointers are now declare as an array. This way all my problems with this initialisation are gone. Everything seems to work fine until I realise one of my conditional branch was always returning false.
The full code is a bit too long and some parts use french words, so let's just paste what interest us...
struct Numero {
int num;
char client[50];
Message *listeMessage = nullptr;
Numero *suivant = nullptr;
int nbmsg = 0;
};
char buff_char[50];
number = new Numero;
file >> number->client; // getting the right char client[50] from the file
if (number->client == buff_char)
break;
I also tried if(*number->client == *buff_char) without success. I'm now thinking that the problem is probably the array of char, but because of my previous problem I can't really change that so I'm hoping somebody can figure out what's going on here.
Note: Don't suggest anything related to strings, I can't use them because it's part of the challenge here to practice with pointers.
number->client == buff_char
Both of these are arrays, which decay into pointers. They are two different arrays with two different addresses, so this will always return false.
*number->client == *buff_char
This would compare the first element in each array, which is also not what you want.
You can use a standard library function like strcmp.
If you can't use the standard library, loop over each array until one has a different element than the other (not equal), they both have '\0' (equal), or they both reach 50 (equal).
In If do a comparison instead of assignment
if (number->client == buff_char)
In C++ = is the assignment operator. You want == for equality. What your if statement does right now is sets client equal to buff_char and then evaluates based on the newly assigned value of client.
I use some function, and this function return variable of LPWSTR type (wchar_t*)
at debugger i look at this variable and see error "0x2e (Address 0x2e out of bounds)"
and when i do some operations with its variable, my program terminated.
I can't change called function, i haven't its src code.
my question is : Is c/c++ language have functions to check situation before call incorrect variable? i try try/catch block, but its not helped.
Excuse me for my english and thanks for any help
edited:
fragment of code with error
PCERT_EXTENSION pCe = CertFindExtension(szOID_CRL_DIST_POINTS, pCertInfo->cExtension, pCertInfo->rgExtension);
if (pCe) {
PCRL_DIST_POINTS_INFO pCrlDistPointsInfo = NULL;
PCRL_DIST_POINT *pCrlDistPointsPtr = NULL;
PCRL_DIST_POINT pCrlDistPoints = NULL;
DWORD pdwCrlDistPoints = sizeof (CRL_DIST_POINTS_INFO);
if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
szOID_CRL_DIST_POINTS,
pCe->Value.pbData,
pCe->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG,
(PCRYPT_DECODE_PARA) NULL,
&pCrlDistPointsInfo,
&pdwCrlDistPoints)) {
printf("\n\nCannot decode CRL URL.\n\n");
}
if (pCrlDistPointsInfo) {
pCrlDistPointsPtr = (PCRL_DIST_POINT*) pCrlDistPointsInfo->rgDistPoint;
if (pCrlDistPointsPtr && pCrlDistPointsInfo->cDistPoint > 0) {
findCDP = true;
fwprintf(pFile, L"^^");
for (int i = 0; i < pCrlDistPointsInfo->cDistPoint; i++) {
pCrlDistPoints = &pCrlDistPointsInfo->rgDistPoint[i];
if (pCrlDistPoints) {
LPWSTR str = (LPWSTR) pCrlDistPoints->DistPointName._empty_union_.FullName.rgAltEntry->_empty_union_.pwszURL;
//printf("last error= 0x%08X", GetLastError());
fwprintf(pFile, str);//PROGRAM TERMINATED HERE!!!
fwprintf(pFile, L";");
}
printf("%d\n",i);
}
}
free(pCrlDistPointsInfo);
}
}
No, it doesn't have. If you set a pointer, which points to an invalid memory location, every access to the object at that location is an undefined behavior. What will most likely happen is a crash or some kind of memory corruption.
If a pointer has value 0x0000002e, it can mean only two things:
A bug in code which returns that. You're out of luck if you can't fix that...
An undefined pointer value, and reason for error is returned some other way, such as by modified reference parameter. But returning undefined value instead of null pointer would still count as a bug in my book.
On the other hand 0x2e sounds like ASCII character, '.' to be exact, so are you sure you are looking at pointer value instead of the string pointed to?
Late edit: looking at the code, it seems unions are involved. A possible reason for crash then is, you are accessing wrong member of union. In C union, all members/fields are in same memory location, they overlap. In other words, union can hold only one value at a time, and you need to know which one somehow, such as from documentation of function which initializes the union value, or by some extra variable which tells the type (common pattern in C is to have struct which contains type field and union field).
Windows has functions to check whether an address is a correct address or not. BUT... it's bad practice to rely on this, since there is no guarantee that if the pointer points to a correct address, that this is the address that you want.
The functions in windows are: IsBadReadPtr, IsBadWritePtr and IsBadCodePtr. I strongly suggest to only use these functions in debugging code (asserts e.g.) and never rely on this in a release executable.
If your application is designed and working correctly, you should never rely on these Windows functions.
If a pointer is set to NULL wouldn't any references to it or through it also be NULL. Here is a compilable example that will bomb when you try to run it:
#include <string>
#include <iostream>
#define NULL 0
class Seedcoat {
public:
//Seedcoat();
std::string Name;
int Weight;
};
class Seed {
public:
//Seed();
std::string Name;
int Weight;
Seedcoat* ItsSeedcoat;
};
class Apple {
public:
//Apple();
std::string Name;
int Weight;
Seed* ItsSeed;
};
int main()
{
///////Apple Objects Begin///////
Apple MyApple;
Seed MySeed;
Seedcoat MySeedCoat;
MyApple.ItsSeed = &MySeed;
MyApple.ItsSeed->ItsSeedcoat = &MySeedCoat;
MyApple.ItsSeed->ItsSeedcoat->Weight = 2;
if ( MyApple.ItsSeed != NULL) {
std::cout << "The weight of the apple seed's seedcoat is " << MyApple.ItsSeed->ItsSeedcoat->Weight <<".\n";
}
MyApple.ItsSeed = NULL;
if ( MyApple.ItsSeed->ItsSeedcoat != NULL) {
std::cout << "The weight of the apple seed's seedcoat is " << MyApple.ItsSeed->ItsSeedcoat->Weight <<".\n";
}
return 0;
}
So my question is: Why does this
MyApple.ItsSeed->ItsSeedcoat != NULL
return true. I would think it would not because ItsSeed is set to NULL - but it still tries to reference the weight value of ItsSeedcoat - and then it bombs I presume because ItsSeed does not exist. I realize there are easy ways to get around this - this example was just to show the behavior I am observing. Is this anything to be concerned about? - or is this normal behavior? What is/are the reason(s) it was done this way? Thanks.
C++ does not hold your hand in such a way. Setting a pointer to null sets only that pointer to null. It doesn't clear any subobjects or free any memory as you might expect in Java or Python.
Once you set the pointer to null, it's no longer legal to access MyApple.ItsSeed->ItsSeedcoat so anything could happen.
In your particular problem I think composition would probably be a better solution. However if you do need to manage memory allocation/deallocation in C++ I highly suggest using an appropriate smart pointer which gives you power approximately equal to that of garbage collectors in other languages.
I do also suggest not defining NULL yourself as some headers already define it for C. In C++03 I typically recommend using the literal 0 while in C++11 you can use the nullptr keyword.
After setting MyApple.ItsSeed to NULL, you are not allowed to dereference the pointer MyApple.ItsSeed, meaning that the expression MyApple.ItsSeed->ItsSeedcoat is not allowed.
This won't necessarily throw an exception, but its behavior is undefined.
It's undefined behavior, and anything can happen.
Particulary,
MyApple.ItsSeed = NULL;
if ( MyApple.ItsSeed->ItsSeedcoat != NULL)
You are not allowed to dereference a NULL pointer. It's as simple as that. If you do, any behavior is compliant.
Dereferencing a NULL pointer leads to undefined behavior. In order to get to the member ItsSeedCoat you have to dereference the pointer ItsSeed, which you have already set to NULL.
In your example you set MyApple.ItsSeed which is a Seed* to NULL, and then when you do MyApple.ItsSeed->ItsSeedcoat you try to dereference a NULL pointer.
After setting a pointer to null, any references to that pointer
are also null. In your code, however, you don't have references
to the pointer; you have two, totally distinct pointer objects,
and what you do to one has no effect on the other. (This is
true in every language I know.)
C++ does not implement the kind of behavior that you are describing. In some languages, an object keeps track of all "weak" pointers to it so that when that object is freed, all of those pointers gets NULL'ed automatically. C++ is not one of those language, however. When an object is freed, NO pointers to that object get NULL'ed automatically. When a particular pointer to an object gets NULL'ed, NO other pointers to the same object get NULL'ed automatically. If you need that kind of behavior, look at boost::weak_ptr or std::weak_ptr.
I have a quick question regarding the scope of dynamic arrays, which I assume is causing a bug in a program I'm writing. This snippet checks a function parameter and branches to either the first or the second, depending on what the user passes.
When I run the program, however, I get a scope related error:
error: ‘Array’ was not declared in this scope
Unless my knowledge of C++ fails me, I know that variables created within a conditional fall out of scope when when the branch is finished. However, I dynamically allocated these arrays, so I cannot understand why I can't manipulate the arrays later in the program, since the pointer should remain.
//Prepare to store integers
if (flag == 1) {
int *Array;
Array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char *Array;
Array = new char[input.length()];
}
Can anyone shed some light on this?
Declare Array before if. And you can't declare array of different types as one variable, so I think you should use to pointers.
int *char_array = nullptr;
int *int_array = nullptr;
//Prepare to store integers
if (flag == 1) {
int_array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char_array = new char[input.length()];
}
if (char_array)
{
//do something with char_array
}
else if (int_array)
{
//do something with int_array
}
Also as j_random_hacker points, you might want to change you program design to avoid lot's of if
While you are right that since you dynamically allocated them on the heap, the memory won't be released to the system until you explicitly delete it (or the program ends), the pointer to the memory falls out of scope when the block it was declared in exits. Therefore, your pointer(s) need to exist at a wider scope if they will be used after the block.
The memory remains allocated (i.e. taking up valuable space), there's just no way to access it after the closing }, because at that point the program loses the ability to address it. To avoid this, you need to assign the pointer returned by new[] to a pointer variable declared in an outer scope.
As a separate issue, it looks as though you're trying to allocate memory of one of 2 different types. If you want to do this portably, you're obliged to either use a void * to hold the pointer, or (less commonly done) a union type containing a pointer of each type. Either way, you will need to maintain state information that lets the program know which kind of allocation has been made. Usually, wanting to do this is an indication of poor design, because every single access will require switching on this state information.
If I understand your intend correctly what you are trying to do is: depending on some logic allocate memory to store n elements of either int or char and then later in your function access that array as either int or char without the need for a single if statement.
If the above understanding is correct than the simple answer is: "C++ is a strong-typed language and what you want is not possible".
However... C++ is also an extremely powerful and flexible language, so here's what can be done:
Casting. Something like the following:
void * Array;
if(flag1) Array = new int[len]
else Array = new char[len];
// ... later in the function
if(flag) // access as int array
int i = ((int*)Array)[0];
Yes, this is ugly and you'll have to have those ifs sprinkled around the function. So here's an alternative: template
template<class T> T foo(size_t _len)
{
T* Array = new T[_len];
T element = Array[0];
return element;
}
Yet another, even more obscure way of doing things, could be the use of unions:
union int_or_char {int i; char c;};
int_or_char *Array = new int_or_char[len];
if(flag) // access as int
int element = Array[0].i;
But one way or the other (or the third) there's no way around the fact that the compiler has to know how to deal with the data you are trying to work with.
Turix's answer is right. You need to keep in mind that two things are being allocated here, The memory for the array and the memory when the location of the array is stored.
So even though the memory from the array is allocated from the heap and will be available to the code where ever required, the memory where the location of the array is stored (the Array variable) is allocated in the stack and will be lost as soon as it goes out of scope. Which in this case is when the if block end. You can't even use it in the else part of the same if.
Another different code suggestion from Andrew I would give is :
void *Array = nullptr;
if (flag == 1) {
Array = new int[input.length()];
} else if (flag == 2) {
Array = new char[input.length()];
}
Then you can directly use if as you intended.
This part I am not sure : In case you want to know if its an int or char you can use the typeid literal. Doesn't work, at least I can't get it to work.
Alternatively you can use your flag variable to guess what type it is.
CARD& STACK::peek()
{
if(cards.size == 0)
{
CARD temp = CARD {-1, -1};
return temp;
}
return cards.back();
}
This is the function I am having trouble with.
CARD is just a struct with two int variables, called rank and suit.
STACK is a class that manages an std::vector<CARD>, that is called cards.
The function is supposed to return a reference to the card on top of the stack, or return the reference to a dummy card if the vector is empty.
First of all, I get a warning that says a reference to a local variable temp is returned. What is wrong with that? How will that effect the function? What do I do about it?
Second, I am trying to use this function with another function I created called cardToString
char* cardToString(CARD& c);
It is supposed to use the rank and suit variables in the passed CARD to look up string values in a table, concatenate the two strings together, and return a pointer to the new string.
So the end result looks like:
cout<<cardToString(deck.peek())<<"\n";
but this line of code will execute up to the cardToString function, then just stop for some reason. It is annoying the hell out of me because it just stops, there is no error message and there does not look like there is anything wrong to me.
Can somebody help me out?
Edit: here is the cardToString function
char *cardToString(const CARD& c)
{
if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
{
std::cout<<"returned null";
return NULL;
}
char *buffer = new char[32];
strcpy(buffer, RANKS[c.r]);
strcat(buffer, " of ");
return strcat(buffer, SUITS[c.s]);
}
I specifically want the function STACK.peek() to return the address of the CARD that already exists on the top of the STACK. It seems to make more sense to do that than to create a copy of the card that I want to return.
First of all, I get a warning that says a reference to a local variable temp is returned. What is wrong with that? How will that effect the function? What do i do about it?
A local variable, as it name implies, is local to the function it belongs to, so it's destroyed as the function returns; if you try to return a reference to it, you'll return a reference to something that will cease to exist at the very moment the function returns.
Although in some cases this may seem to work anyway, you're just being lucky because the stack hasn't been overwritten, just call some other function and you'll notice it will stop working.
You have two choices: first of all, you can return the CARD by value instead of reference; this, however, has the drawback of not allowing the caller to use the reference to modify the CARD as is stored in the vector (this may or may not be desirable).
Another approach is to have a static dummy CARD instance stored in the STACK class, that won't have these lifetime problems, and that can be returned when you don't have elements in the vector; however, you should find a method to "protect" its field, otherwise a "stupid" caller may change the values of your "singleton" dummy element, screwing up the logic of the class. A possibility is to change CARD in a class that will encapsulate its fields, and will deny write access to them if it's the dummy element.
As for the cardToString function, you're probably doing something wrong with the strings (and I'm almost sure you're trying to return a local also in this case), but without seeing the body of the function it's difficult to tell what.
By the way, to avoid many problems with strings I suggest you to use, instead of char *, the std::string class, which takes away most of the ugliness and of the low level memory management of the usual char *.
Also, I'd suggest you to change cardToString to take a const reference, because most probably it doesn't need to change the object passed as reference, and it's good practice to clearly mark this fact (the compiler will warn you if you try to change such reference).
Edit
The cardToString function should be working fine, as long as the RANKS and SUITS arrays are ok. But, if you used that function like you wrote, you're leaking memory, since for each call to cardToString you make an allocation with new that is never freed with delete; thus, you are losing 32 bytes of memory per call.
As stated before, my tip is to just use std::string and forget about these problems; your function becomes as simple as this:
std::string cardToString(const CARD& c)
{
if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
return "(invalid card)";
return std::string(RANKS[c.r]) + " of " + SUITS[c.s];
}
And you don't need to worry about memory leaks and memory allocations anymore.
For the reference/value thing: if the caller do not need to use the reference to modify the object stored in the vector, I strongly suggest passing it by value. The performance hit is negligible: two ints instead of one pointer means 8 vs 4 bytes on most 32 bit architectures, and 8 bytes vs 8 bytes on most 64 bit machines (and also accessing the fields via pointer has a small cost).
This kind of micro-optimization should be the last of your concerns. Your top priority is to write correct and working code, and the last thing you should do is to let micro-optimization get in the way of this aim.
Then, if you experience performance problems, you'll profile your application to find where the bottlenecks are and optimize those critical points.
You cannot return a reference to a local variable, because the local variable no longer exists when the function returns.
You need to return by-value, not by-reference (i.e. CARD STACK::peek() { ... }).