OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Feb 26, 2024 2:28 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Strings getting deleted at the wrong time in c++
PostPosted: Mon Oct 23, 2023 3:42 pm 
Offline
Member
Member

Joined: Thu Aug 25, 2022 3:54 pm
Posts: 27
I'm trying to understand the deconstructor in c++. I thought I understood how deconstructors work but turns out I don't.

I have the following pseudo code:
Code:
do_the_string_bug()
{
   string var1 = "var1";
   printString(var1);      //var1 prints to screen correctly but the deconstructor get called when it returns
   printString("...");      //"..." prints to the screen correctly
   printString(var1);      //since the char array inside var1 has been deallocated and since "..." was the next string that got allocated, it now prints "...1" because that memory was overwritten
}
void printString(const string text)
{
   for (int i = 0; i < text.length(); i++)
   {
      printChar(text.at(i));
   }
}


In my program, once the code gets to the end of the print string function, it deletes the string that was passed to it causing the char array inside it to get deallocated. This means that other data can overwrite it causing all kinds of nasty bugs. I can remove the code that frees the char array. This stops the weird string bugs I keep having by preventing the printString function from being able to delete them but then every string operation becomes a memory leak since strings can no longer be deleted when the function that actually created the strings returns.

Why are functions calling the deconstructor on strings that get passed to them despite the const keyword?


Top
 Profile  
 
 Post subject: Re: Strings getting deleted at the wrong time in c++
PostPosted: Mon Oct 23, 2023 3:52 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
1) They are called destructors, not deconstructors.
2) You pass the string by value, not reference. This means the string is copied when you call the printString() function.
3) At the end of printString() the copied string (text) gets deleted because it goes out of scope.
4) The original string's destructor doesn't get called until the end of do_the_string_bug(). What I think is happening here is that you have not implemented a copy constructor for string and so the raw data pointer is copied as is. So you now have two different strings pointing to the same data.
5) "const" doesn't do anything at runtime, it's purely a compile time construct that has no impact on code generation. It cannot detect logic errors in your code at runtime. It certainly cannot prevent a destructor from being called.

You need to do something about copying strings:
1) Make copy unavailable.
2) Implement a copy constructor that copies the data (easier, less efficient).
3) Implement reference counting for the raw data (more difficult, more efficient).

You also probably most likely want to pass the string by reference and not by value.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Strings getting deleted at the wrong time in c++
PostPosted: Mon Oct 23, 2023 5:56 pm 
Offline
Member
Member

Joined: Thu Aug 25, 2022 3:54 pm
Posts: 27
Ok thanks. I did experiment with copy constructors and found that a lot more stuff is likely messed up than I thought. No idea how I've gotten so far if that's the case, maybe I just got incredibly lucky to have everything string related mostly work except for this new bug I've only recently discovered. I tried substituting my memory allocator for the liballoc one which only causes it to crash sooner than before when I run it with the new copy constructor. Normally it works the same and gives me the same bug (but it crashes during keyboard scancode setup, a thing that doesn't crash when using my memory allocator) Would be nice if there was a c++ dynamic array that that uses no outside libraries so I could substitute that in and see if my vector equivalent class is broken or not but there isn't one.
Code:
string :: string(const string &str)
{
    //charArray.clear();
    //charArray.resize(10);
    for (int i = 0; i < str.length(); i++)
    {
        charArray.push_back(str.at(i));
    }
}

string& string :: operator=(const string& other)
{
    //charArray.clear();
    //charArray.resize(10);
    for (int i = 0; i < other.length(); i++)
    {
        charArray.push_back(other.at(i));
    }

    return *this;
}


This is what I'm pretty sure the most correct implementation of the string copy constructor is. charArray is a dynarray<char> object that works exactly the same as vector.

It should also be noted that in my system, I need to be able to manually define where in memory allocated memory should be stored. For example I need stuff to be saved at 0x20000 and up instead of some random location beyond my control that's probably conflicting with stuff. I think liballoc_alloc is intended to be used for this but I still haven't figured out how it is meant to be used. The best hack I could come up with was making liballoc_alloc always return (void*)0x20000 since it only ever seems to call liballoc_alloc if there are no tags or pages already in memory and it allocates the next block based on where the previous one is. It doesn't seem to be writing things to anywhere besides location 0x20020 though.


Top
 Profile  
 
 Post subject: Re: Strings getting deleted at the wrong time in c++
PostPosted: Mon Oct 23, 2023 10:48 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5045
SomeGuyWithAKeyboard wrote:
Would be nice if there was a c++ dynamic array that that uses no outside libraries so I could substitute that in and see if my vector equivalent class is broken or not but there isn't one.

I'm sure it's not trivial, but you can always try ripping the std::vector implementation out of libstdc++. That should only rely on other libstdc++ pieces and a working malloc.

SomeGuyWithAKeyboard wrote:
It should also be noted that in my system, I need to be able to manually define where in memory allocated memory should be stored.

That's usually how it works in an OS kernel.

SomeGuyWithAKeyboard wrote:
I think liballoc_alloc is intended to be used for this but I still haven't figured out how it is meant to be used.

It's meant to hook into your page allocator. In a typical OS using paging, that would be a call to the virtual memory manager to find an appropriate range of virtual addresses and populate them with pages allocated via the physical memory manager.

SomeGuyWithAKeyboard wrote:
The best hack I could come up with was making liballoc_alloc always return (void*)0x20000 since it only ever seems to call liballoc_alloc if there are no tags or pages already in memory and it allocates the next block based on where the previous one is.

It needs to return free memory (or NULL) every time it's called. I don't think liballoc will behave very well if you give it the same address twice.


Top
 Profile  
 
 Post subject: Re: Strings getting deleted at the wrong time in c++
PostPosted: Mon Oct 23, 2023 11:12 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
Using a dynamic array like std::vector<> and doing push_back() to copy strings one character at a time is not going to be very efficient. It would be better to just malloc a block of memory to hold the whole string and use memcpy() to copy the characters.

Code:
string::string(const string& other)
{
    size = other.size();
    data = (char*)malloc(size+1); // +1 for the '\0' string terminator
    memcpy(data, other.data, size+1); // ditto
}

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Strings getting deleted at the wrong time in c++
PostPosted: Tue Oct 24, 2023 6:18 am 
Offline
Member
Member

Joined: Mon Jul 05, 2021 6:57 pm
Posts: 118
SomeGuyWithAKeyboard wrote:
Would be nice if there was a c++ dynamic array that that uses no outside libraries so I could substitute that in and see if my vector equivalent class is broken or not but there isn't one.


https://github.com/davmac314/libbmcxx

It's not much, but it has a basic `std::vector` implementation.


Top
 Profile  
 
 Post subject: Re: Strings getting deleted at the wrong time in c++
PostPosted: Sat Oct 28, 2023 6:02 am 
Offline
Member
Member
User avatar

Joined: Thu Nov 16, 2006 12:01 pm
Posts: 7610
Location: Germany
Obligatory links to the Wiki, Required Knowledge item 5 (Programming Experience), and Beginner Mistakes, "A hard truth".

If C++ destructors, the rule of three / five / zero, and passing by value vs. passing by reference throw you off course, you should re-evaluate if you really want to learn about those in kernel space (hint: you do not). Things will get a lot more complicated than that. A standalone "printString()" function does not speak for C++ fluency either. No offense intended, these are mistakes that are in the Wiki for a reason.

_________________
Every good solution is obvious once you've found it.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group