Weird problem with BAD POINTER
Hi
Say I have a struct
struct Object
{
char Name[256];
};
now I have a list of objects printed. Say the first two objects don't have a name. So the variable Name wasnt even touched.
for( int i=0; i<ListObjects.Count; i++)
{
if( ListObjects.Name )
cout << ListObjects.Name;
else
cout << "No name";
}
Now in the first loop i==0 the if statement fails because the first object has no name (array was not initialized) to anything. Simply it wasnt touched. Now when debugging it the debugger says 0x00000000 <Bad Ptr> and the if statement fails which is fine and else is executed. But the problem is that in the second loop the object isnt intialized too and the debugger displays very similar message 0x00000080 <Bad Ptr> but this time the if statement executes which causes the program to crash. It shouldnt enter the if() its a bad pointer.. why does it enter??? I tried also if( ListObjects.Name != NULL ) but same thing. it crashes.
Now I am not allowed to add anything to that structure and I have to find a way to make this check correct so the program doest enter if() when there is a bad pointer so it doesnt crash. I agree its a poor design but thats what I have to deal with :( Any ideas how else?
what you are doing is very strange, because you
shouldnt really test if .Name is allocated, you have
explicitly defined the size of the array in the struct, this
this should not be treated as a heap-pointer.
here is how i would implement what you want (in C++):
Implementation:
shouldnt really test if .Name is allocated, you have
explicitly defined the size of the array in the struct, this
this should not be treated as a heap-pointer.
here is how i would implement what you want (in C++):
const int MAX_SIZE = 256;struct Object { // default constructor Object() { memset(name, 0, MAX_SIZE); } // const char constructor Object( const char *c ) { strncpy(name, c, MAX_SIZE); } // copy constructor Object(const Object& rhs) { strncpy(name, rhs.name, MAX_SIZE); } // copy operator Object& operator=(const Object& rhs) { strncpy(name, rhs.name, MAX_SIZE); return *this; } char name[MAX_SIZE];};
Implementation:
#include <iostream>#include <vector>using namespace std;int main(){ vector< Object > p; p.push_back( Object("something") ); p.push_back( Object("") ); p.push_back( Object("something") ; // should use vector< >::iterator here ! for(int i=0; i<(int)p.size(); i++) { if( strcmp(p.name, "") != 0 ) { cout << p.name << endl; } else { cout << "No Name!" << endl; } }}
Hi.
the if condition test the value of the pointer, not its validity.
Your problem is that "Name" is initialized as for each Object, the array is allocated.
the difference between "char Name[256]" and "char* Name" is that in the first case, Name points to a 256 char allocated memory zone, even if you don't fill the array with a real name. And if the array is not initialized to something, then great chances are that it contains garbage values.
In the second case ( "char* Name" ), the Name attribute is a pointer on a memory zone that contains char values. But, in that case, the memory zone is NOT allocated till you don't make the allocation .
Exemple :
char* lName; // create the pointer
lName = new char[256]; // allocate memory and make the pointer points on it
However, even in the second case, you can make no assumptions on the value of the pointer ! That's why, it is preferable to initialize the pointer to 0 when you create it:
char* lName=0;
in that case, you will be able to test the validity of the pointer, as if it is undefined, then it's value is 0, whereas its value is different if you have initialized it with a "lName = new char[256];"
In your case where you cannot change your struct Object, nor add a boolean value to set the validity of the Name, there is one way to handle it, but it will be... very ugly ( and there's a chance that it won't even be possible if you haven't access to the function that fills the Name attributes... )
Try to initialize the first element of the Name array to a value that cannot possibly exist in a real Name ( like Name[0] = 127 ), and test its value in your if() condition. However, it's strange that your debugger reference the Name attributes as a <Bad Pointer> as it should be initialized...
the if condition test the value of the pointer, not its validity.
Your problem is that "Name" is initialized as for each Object, the array is allocated.
the difference between "char Name[256]" and "char* Name" is that in the first case, Name points to a 256 char allocated memory zone, even if you don't fill the array with a real name. And if the array is not initialized to something, then great chances are that it contains garbage values.
In the second case ( "char* Name" ), the Name attribute is a pointer on a memory zone that contains char values. But, in that case, the memory zone is NOT allocated till you don't make the allocation .
Exemple :
char* lName; // create the pointer
lName = new char[256]; // allocate memory and make the pointer points on it
However, even in the second case, you can make no assumptions on the value of the pointer ! That's why, it is preferable to initialize the pointer to 0 when you create it:
char* lName=0;
in that case, you will be able to test the validity of the pointer, as if it is undefined, then it's value is 0, whereas its value is different if you have initialized it with a "lName = new char[256];"
In your case where you cannot change your struct Object, nor add a boolean value to set the validity of the Name, there is one way to handle it, but it will be... very ugly ( and there's a chance that it won't even be possible if you haven't access to the function that fills the Name attributes... )
Try to initialize the first element of the Name array to a value that cannot possibly exist in a real Name ( like Name[0] = 127 ), and test its value in your if() condition. However, it's strange that your debugger reference the Name attributes as a <Bad Pointer> as it should be initialized...
Ok. thank you for your replies.
Silly me. The list was invalid thus this bad ptr not the array. I am sorry haha :)
Actually I have one more question to "srom" & "silvermace":
if you try to print out value of "n1" (below) the program will crash its because the pointer isnt initialized. It may point at some location I dont know. Well it must point somwhere.
Now n2[1] was not initialized and it has a pointer to its first element and it points somwhere too but the program doesnt crash why? they both are not initialized and point at some location in memory. I guess coze arrays are intialized by default to 0 aren't they or its other reason???
char *n1;
char n2[1];
cout << *n1<< endl; // this crashes!!
cout << n2[0] << endl; // this is ok
Silly me. The list was invalid thus this bad ptr not the array. I am sorry haha :)
Actually I have one more question to "srom" & "silvermace":
if you try to print out value of "n1" (below) the program will crash its because the pointer isnt initialized. It may point at some location I dont know. Well it must point somwhere.
Now n2[1] was not initialized and it has a pointer to its first element and it points somwhere too but the program doesnt crash why? they both are not initialized and point at some location in memory. I guess coze arrays are intialized by default to 0 aren't they or its other reason???
char *n1;
char n2[1];
cout << *n1<< endl; // this crashes!!
cout << n2[0] << endl; // this is ok
The problem has nothing to do with bad pointers. They aren't really typical pointers to heap memory at all. You'll notice that your first one's value was 0x00000000, and the second one was 0x00000080. Those are values 0 and 256 respectively. That's just the location on the stack where they are. I can't do math. 0x80 is 128. Nonetheless, these values aren't relevant.
The reason some things are crashing is because the data in the array is not a valid string. Strings need to end with a terminating null zero ('\0') to be valid. Your unitialized arrays probably don't contain a null zero, however, so when you output the array, the output function keeps on reading characters, waiting for a null zero to be found, which never is. So it keeps reading characters, and eventually reads memory that it isn't allowed to read. This is what is causing the crash. Try setting the first element in each array equal to '\0'. This initializes each array to be a zero-length string. Then you can test the first character for equalling '\0' to see if it is an empty string or not.
Bottom line: Initialize your data, or else you're stuck.
The reason some things are crashing is because the data in the array is not a valid string. Strings need to end with a terminating null zero ('\0') to be valid. Your unitialized arrays probably don't contain a null zero, however, so when you output the array, the output function keeps on reading characters, waiting for a null zero to be found, which never is. So it keeps reading characters, and eventually reads memory that it isn't allowed to read. This is what is causing the crash. Try setting the first element in each array equal to '\0'. This initializes each array to be a zero-length string. Then you can test the first character for equalling '\0' to see if it is an empty string or not.
Bottom line: Initialize your data, or else you're stuck.
First off you do not dereference a pointer when u try to cout it.
cout<< *n1; //BAD!!
cout<<n1;//good
It crashes because the pointer is not pointing to absolutly anything, and cout is not liking it. you ALWAYS and i do mean ALWAYS have to initialize pointers and for that matter all your variables to something. its just good programing practice.
As for why the Array doesnt crash well its simple the array already has memory allocated to it, so it has some values in it(even though they are garbage)
cout<< *n1; //BAD!!
cout<<n1;//good
It crashes because the pointer is not pointing to absolutly anything, and cout is not liking it. you ALWAYS and i do mean ALWAYS have to initialize pointers and for that matter all your variables to something. its just good programing practice.
As for why the Array doesnt crash well its simple the array already has memory allocated to it, so it has some values in it(even though they are garbage)
char *n1; // n1 is a random value, though probably 0, and thus// points at memory that you probably don't own.char n2[1]; // This implicitly grabs one byte worth of space that// you now own (although it is in an effectively random location,// and contains an effectively random value), and points at that.cout << n1 << endl; // prints some randomish pointer valuecout << *n1<< endl; // Tries to grab the value being pointed at,// but it's not yours. Boom.cout << n2[0] << endl; // Tries to grab the first element of the// array; it belongs to you, but doesn't contain anything// meaningful.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement