I am using C++ Builder XE4 on Windows7 Professional (32bit).
I have a question on TStringList;
What I would like to do is to know whether the TStringList variable was newed or not, to prevent Add() method to non-newed TStringList;
I thought checking NULL might work, but it didn't.
TStringList *list;
// list = new TStringList(); // someone commented out by mistakes
if (list == NULL) {
ShowMessage(L"NULL");
} else {
ShowMessage(L"not empty");
}
return;
The above code shows "not empty" dialog.
What is a standard way to check the newed or non-newed TStringList?
It is very commonplace is c/c++ to initialize pointers to NULL, and have them be null whenever they aren't pointing at something valid.
As such, your if statement is a very commonplace and appropriate piece of code.
However, this does require initializing your variable.
Unless declared at global/file scope, the line: TStringList *list; does not initialize the variable to any specific value - this leaves it pointing at random crap.
You need to change it to TStringList *list = NULL; (or similar, some people dont like "NULL")
Related
what is the difference of pointers between and which is better in terms of memory management
void Loo(){
Song* pSong = new Song(…);
//…
string s = pSong->duration;
}
and
void Hoo(){
unique_ptr<Song> song2(new Song(…));
//…
string s = song2->duration;
}
In the first case you need to call delete yourself and make sure it happens on all program control paths.
That is easier said than done. It's tempting to write delete pSong; just before the closing brace of the function and be done with it. But what happens, say, if string s = song2->duration throws an exception? (Yes it's possible; for example if song2->duration is a type that has a conversion operator defined so it can be assigned to a string.)
With std::unique_ptr, delete will be called for you when it goes out of scope.
Although in this particular case Song song(...); may be more appropriate.
So I recently got a hold of RapidXML to use as a way to parse XML in my program, I have mainly been using it as a way to mess around but I have been getting some very weird issues that I'm really struggling to track down. Try and stick with me through this, because I was pretty thorough with trying to fix this issue, but I must be missing something.
First off here's the XML:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<image key="tilemap_roguelikesheet" path="res/media/tilemaps/roguelikesheet.png" />
<image key="tilemap_tiles" path="res/media/tilemaps/tiles.png" />
</resources>
The function the segfault occurs:
void TextureManager::LoadResource(const char* pathToFile)
{
rapidxml::xml_document<>* resource = Resources::LoadResource(pathToFile);
std::string imgName;
std::string imgPath;
if (resource != NULL)
{
rapidxml::xml_node<>* resourcesNode = resource->first_node("resources");
if (resourcesNode != NULL)
{
for (rapidxml::xml_node<>* child = resourcesNode->first_node("image"); child; child = child->next_sibling())
{
//Crash here on the second loop through.
imgName = child->first_attribute("key")->value();
imgPath = child->first_attribute("path")->value();
Astraeus::Log(moduleName, "Image Name: " + imgName);
Astraeus::Log(moduleName, "Image Path: " + imgPath);
TextureManager::AddTexture(imgName, imgPath);
}
}
else
{
Astraeus::Error(moduleName, "Resources node failed to load!");
}
resource->clear();
}
else
{
std::string fileName(pathToFile);
Astraeus::Error(moduleName, fileName + " could not be loaded.");
}
}
So segfault happens on the second loop of the for loop to go through all the nodes, and triggers when it tries to do the imgName assignment. Here's where things get a bit odd. When doing a debug of the program, the initial child nodes breakdown shows it has memory pointers to the next nodes and it's elements/attributes etc. When investigating those nodes, you can see that the values exist and rapidxml has seemingly successfully parsed the file.
However, when the second loop occurs, child is shown to still have the exact same memory pointers, but this time the breakdown in values show they are essentially NULL values, so the program fails and we get the code 139. If you try and look at the previous node, that we have just come from the values are also NULL.
Now say, I comment out the line that calls on the AddTexture function, the node is able to print out all the nodes values no problems at all. (The Log method is essentially just printing to console until I do some more funky stuff with it.) so the problem must lie in the function? Here it is:
void TextureManager::AddTexture(const std::string name, const std::string path)
{
Astraeus::Log(moduleName, "Loading texture: " + path);
if (texturesLookup.find(name) != texturesLookup.end())
{
Astraeus::Error(moduleName, "Texture Key: " + name + " already exists in map!");
}
else
{
texturesLookup.insert(std::make_pair(name, path));
//Texture* texture = new Texture();
/*if (texture->LoadFromFile(path))
{
//textures.insert(std::make_pair(name, texture));
}
else
{
Astraeus::Error(moduleName, "Failed to add texture " + name + " to TextureManager!");
}*/
}
}
Ignoring the fact that strings are passed through and so should not affect the nodes in any way, this function is still a bit iffy. If I comment out everything it can work, but sometimes just crashes out again. Some of the code got commented out because instead of directly adding the key name, plus a memory pointer to a texture, I switched to storing the key and path strings, then I could just load the texture in memory later on as a workaround. This solution worked for a little bit, but sure enough began to segfault all over again.
I can't really reliably replicate or narrow down what causes the issue everytime, so would appreciate any help. Is RapidXML doc somehow going out of scope or something and being deleted?
For the record the class is practically just static along with the map that stores the texture pointers.
Thanks!
So for anybody coming back again in the future here's what was happening.
Yes, it was a scope issue but not for the xml_document as I kept initially thinking. The xml_file variable that was in the resources load function was going out of scope, which meant due to the way RapidXML stores things in memory, as soon as that goes out of scope then it frees up the memory, which led to the next time dynamic allocation happened by a specific function it would screw up the xml document and fill it with garbage data.
So I guess the best idea is to make sure xml_file and xml_document do not go out of scope. I have added some of the suggestions from previous answers, but I will point out those items WERE in the code, before being removed to help with the debug process.
Thanks everybody for the help/advice.
I'm not sure, but I think that Martin Honnen made the point.
If next_sibling() return the pointer to the text node between the two "image" elements, when you write
imgName = child->first_attribute("key")->value();
you obtain that child->first_attribute("key") is a null pointer, so the ->value() is dereferencing a null pointer. Crash!
I suppose you should get the next_sibling("image") element; something like
for (rapidxml::xml_node<>* child = resourcesNode->first_node("image");
child;
child = child->next_sibling("image"))
And to be sure not to use a null pointer, I strongly suggest you to check the attribute pointers (are you really sure that "image" elements ever carry the "key" and the "path" elements?); something like this
if ( child->first_attribute("key") )
imgName = child->first_attribute("key")->value();
else
; // do something
if ( child->first_attribute("path") )
imgPath = child->first_attribute("path")->value();
else
; // do something
p.s.: sorry for my bad English.
This line is setting my teeth on edge...
rapidxml::xml_document<>* resource = Resources::LoadResource(pathToFile);
LoadResource returns a pointer, but you never free it anywhere...?
Are you 100% sure that function isn't returning a pointer to an object that's now gone out of scope. Like this classic bug...
int * buggy()
{
int i= 42;
return &i; // UB
}
As #max66 says. You should use next_sibling("image"). If that's failing, you need to find out why.
I have a class:
class A
{
public:
void foo(void)
{
// equals to syntactically incorrect (&this == nullptr)
if (*(void**)this == nullptr)
return;
...
}
};
I use it like this:
A * a = new A;
...
delete a;
...
a->foo();
Why the condition is true for release version only? If I switch to debug version, I usually get something like 0xFEEFEEFE.
EDIT
Ok guys. What you said is absolutely right, and I knew that.
Undefined behavior is something that is not specified by standard.
This is what every platform implements (but implements) in its own way.
The purpose of this question is to understand how is it implemented in Windows. This code always works properly ('always properly' means: on all versions of Windows (starting with xp) with any compiler the method is called and the statement is true)). In my case I want to know what usually happens if the object is deleted in Windows.
P.S.
I should have asked this question in wasm.ru. Sorry.
Why would this be true at all? It's unspecified what the value of a pointer is after deleting it. Implementations are not required to set pointers to null after deleting them. And really this should never be null unless you're already in crazy town.
Edit: After OP shows more code:
A * a = new A;
...
delete a;
...
a->foo();
Yeah, that line a->foo();? That's like the most surefire way to get undefined behavior.
You assume that delete will put nullptr into variable that holds pointer being deleted. This is not true, delete is not doing things like that.
Why the condition is true for release version only? If I switch to debug version, I usually get something like 0xFEEFEEFE.
When you call delete a; under Windows, CRT library will mark memory under a pointer as freed. In debug mode it additionally puts into this memory region 0xFEEFEEFE values, which simply means freefree. This makes it easier to find during debugging cases when freed memory is being used. In release mode CRT is not puting this value after delete.
if (*(void**)this == nullptr)
In this case this pointer is declared as class-type * this, so casting it to (void**) is simply wrong.
a->foo();
this is wrong, after delete you should not use a - it causes UB
I am writing an application using the crypto++ library. For those not familiar with it, the ECB_Mode template classes inherit from CipherModeBase. The program compiles and runs, but the output I am getting is incorrect. When I call the encryption method from the cipher_object, it doesn't work the same way as if I use an ECB_Mode object directly. I have verified that the options object instance variables are getting assigned correctly. I would like to create the instances within an if_then_else structure or switch_case so I can keep the code nice and DRY. What am I doing wrong?
Here is what I am trying but doesn't work:
CipherModeBase *cipher_object;
cipher_object == NULL;
if(options->cipher == BS_AES)
{
ECB_Mode<AES >::Encryption ecbEncryption(options->key, options->keylen);
cipher_object = &ecbEncryption;
}
else if(options->cipher == BS_TWOFISH)
{
ECB_Mode<Twofish >::Encryption ecbEncryption(options->key, options->keylen);
cipher_object = &ecbEncryption;
}
cipher_object->processData(args);
Here is what does work:
ECB_Mode<AES >::Encryption ecbEncryption(options->key, options->keylen);
ecbEncryption.processData(args);
PS. I know not to use ECB mode. I just don't want to mess with IVs until I can get everything working. I am also relatively inexperienced with C++.
Your ecbEncryption objects are declared on the stack within the if and else scopes. (Scopes are the things enclosed by curly brackets).
An object will be destroyed when the scope it was declared in exits. So, the object you're calling processData on has been deleted before you call that method. Clearly that won't work.
One option is you could declare the objects on the heap instead of the stack. That way the lifetime could be controlled to work the way you want.
Try to use a std::unique_ptr for the cipher_object instead of a raw pointer. Then, in the if and else clauses assign to it like:
cipher_object.reset( new ECB_Mode<AES>::Encryption(options->key, options->keylen) );
Then the object will remain on the heap until the end of the cipher_object's scope, at which point the unique_ptr will delete it for you. And, the cipher_object's scope will last until after you call any methods on it.
Here:
cipher_object == NULL;
if(options->cipher == BS_AES)
{
// v
ECB_Mode<AES >::Encryption ecbEncryption(options->key, options->keylen);
cipher_object = &ecbEncryption;
}
ecbEncryption is local to that scope. You are storing the address of a local, and using it after it goes out of scope. That's undefined behaviour. You should allocate it on the heap using the new keyword:
if(options->cipher == BS_AES)
{
cipher_object = new ECB_Mode<AES >::Encryption(options->key, options->keylen);
}
You should do the same for the other if statement.
Also note that this:
cipher_object == NULL;
Should be changed to this:
cipher_object = NULL;
The problem should be solved using the above code, though.
The main goal of the Null Object Pattern is to ensure that a usable object is provided to the client. So we want to replace the following code...
void Class::SetPrivateMemberA() {
m_A = GetObject();
}
void Class::UseA() {
if (m_A != null) {
m_A.Method();
} else {
// assert or log the error
}
}
...with this implementation:
void Class::SetPrivateMemberA() {
m_A = GetObject();
}
void Class::UseA() {
m_A.Method();
}
The problem I am thinking of is that GetObject() still returns an object, a NULL Object or otherwise. I like the idea of not checking for null repeatedly and trusting that the object sent back is usable, but why wouldn't I just do that in the first implementation?
Is the advantage of the Null Object pattern just a slight increase in trust to clean up code? With the second implementation, is it not still a good practice to check that it is not null before calling A.Method()?
You're correct that, if you're sure you're never returning nulls, just skip the null check before calling the method in your first implementation. Likewise, if you do need to do something special in the case that UseA() needs to do something differently on a null object, that you need to explicitly check for a null object anyway. However, what null object pattern really helps with is those situations where it doesn't really matter.
Take, for example, most observer patterns. If you implement your observer pattern as a member of your class for which there can only be one observer, and want to announce to the observer that your class did something, it doesn't matter to the class whether the observer is null or not.
This is also illustrated with empty container classes, which are essentially the null object pattern: Instead of returning a null container from a query, you simply return an empty container. For things like iterating through all entries of a container, it often won't matter whether it's empty or not, so getting rid of the need of a null check makes the code more maintainable/more readable. However, if you want to populate a view of your data set, you still need to explicitly show a different "No entries." that checks for an empty container.
Edit for clarity
One problem is only looking at it from the call site. Like most design patterns, this needs to encompass both sides to be fully utilized. Consider:
public PossiblyNull GetSomethingNull()
{
if (someBadSituation())
return null;
else
return SomehowProduceSomething();
}
vs
public PossiblyEmpty GetSomethingEmpty()
{
if (someBadSituation())
return StaticEmptySomething();
else
return ProdueSomethingYay();
}
Now, your call code, instead of looking like
public void DoSomethingWithChild(Foo foo)
{
if (foo != null)
{
PossiblyNull bar = foo.GetSomething();
if (bar != null)
bar.DoSomething();
}
}
it can be
public void DoSomethingWithChild(Foo foo)
{
if (foo != null)
foo.GetSomething().DoSomething();
}
With the second implementation, is it
not still a good practice to check
that it is not null before calling
A.Method()?
No. If you know that m_A is not null, then the check is superfluous; it's an example of paranoid coding. What harm does it do? It complicates your code - unnecessarily; it makes it harder to read, harder to debug.