0

Is it good to check pointer with 0xDD or 0xCC or 0xFD, or 0xCD IF its not NULL? I am writing plugin for Unity3D, which supports C with some features of C++. So new is not allowed in here.

char** m_strArry;

void FreeChar(char* a_data)
{
    free(a_data);
    a_data = NULL;
}

void Test_PointerReference2()
{
    m_strArry = (char**)malloc(3);

    char* l_str1 = (char*)malloc(5);
    strcpy_s(l_str1, 5, "Test");

    char* l_str2 = (char*)malloc(7);
    strcpy_s(l_str2, 7, "String");

    char* l_str3 = (char*)malloc(5);
    strcpy_s(l_str3, 5, "Here");

    m_strArry[0] = l_str1;
    m_strArry[1] = l_str2;
    m_strArry[2] = l_str3;

    FreeChar(l_str2);

    for (int l_index = 0; l_index < 3; l_index++)
    {
        char* l_data = m_strArry[l_index];    //ISSUE: FOR l_index=1(OR l_str2) l_data is a valid address with garbage data.
        if(l_data == NULL)
            printf_s("\nIndex %d is NULL", l_index);
        else
            printf_s("\nIndex %d = '%s'", l_index, l_data);
    }
}

So i fixed the above issue by sending pointer-reference to FreeChar(). i.e.,

void FreeChar(char*& a_data)
{
    free(a_data);
    a_data = NULL;
}

with above code, i am getting pointer value of m_strArry[1] OR l_str2 as NULL.

But in some of my cases, i am getting poitner value as 0xDD (i.e., The memory locations filled are Released heap memory). I read on this link that 0xDD, 0xCC, 0xFD, and 0xCD are reserved address.

So, Is it good (or good practice) to check pointer with 0xDD or 0xCC or 0xFD, or 0xCD besides checking for NULL? If i shouldn't check for any reason, then what is the solution to this issue?

Vilx-
  • 104,512
  • 87
  • 279
  • 422
SatbirSingh
  • 198
  • 1
  • 11
  • 8
    If you are using references then you are writing C++, so why are you using `malloc` or raw pointers at all? – UnholySheep Jan 15 '18 at 08:17
  • 2
    No, it's not a good practice. It's compiler-dependent, and probably won't work in release build. If you need that check, it means that the code is broken. And why check anyway, if any of the values are encountered, the program will probably crash anyway. – HolyBlackCat Jan 15 '18 at 08:17
  • 1
    This can't be about C, since you're asking about reference parameters, which are only C++. – Barmar Jan 15 '18 at 08:19
  • @UnholySheep: I am using C and C++ both. I am working on a plugin for Unity3D. Unity3D do not allow to use new but some c++ features. I have edited my question. – SatbirSingh Jan 15 '18 at 08:20
  • What are you talking about? Unity3D does not put any such restrictions on C++ code (not that it could anyway, since it only calls into a function, it does not compile or influence the way it works internally at all) – UnholySheep Jan 15 '18 at 08:22
  • @UnholySheep: Sorry about this, I'll check for this again tonight. But i need solution to actual problem. – SatbirSingh Jan 15 '18 at 08:28

1 Answers1

7

No, it's not a good practice at all. Those values are undocumented unofficial and unreliable. They might change in the future. In the release build they might not show up at all.

If you get a problem like this, that means you have a bug. And in this case, it's here:

m_strArry = (char**)malloc(3);

3 bytes is far too little to hold 3 pointers. You need:

m_strArry = (char**)malloc(3 * sizeof(char*));

As noted in the comments, that's only half the problem. The other half is the fact that FreeChar(l_str2); doesn't reset m_strArry[1] to null.

Yes, that is legit. C/C++ doesn't keep track what is copied where. It's your responsibility as a developer to make sure that all the pointers to a block of memory are properly disposed of after the memory is released. Failing to do so is called a "dangling pointer" and it's a VERY common mistake to make in C/C++. This can wreak all sorts of havoc on your program, from crashes to corrupted data. In fact, it's probably one of the most widespread causes of program crashes out there.

Vilx-
  • 104,512
  • 87
  • 279
  • 422
  • Issue is not with allocation, but in for-loop. While traversing. l_str2 is freed in FreeChar() function but l_str2 in Test_PointerReference2() is still holding the address. – SatbirSingh Jan 15 '18 at 08:24
  • @SatbirSingh - Ahh, yes, you're right. That too. Well, C/C++ doesn't track which pointer is copied where. Consider this: `char *a = "hello"; char * b = a; char *c = a; a = null;` Would you expect `b` and `c` to also be `null` after this? Of course not. Same thing here. It's your responsibility as a developer to set `m_strArry[1]=null;` at the right time. – Vilx- Jan 15 '18 at 08:28
  • @SatbirSingh How do you know? You don't use `l_str2` after freeing it. – Gerhardh Jan 15 '18 at 08:30
  • @Gerhardh - Debugger, I expect. Also, I get the feeling he has the illusion that after setting `m_strArry[1] = l_str2;` these two values are somehow magically linked and setting one sets the other (thus he uses them interchangeably in conversation) – Vilx- Jan 15 '18 at 08:40
  • @Vilx- I also have this impression. He might think that printing `l_data` for index 1 is same as `l_str2` which is not. – Gerhardh Jan 15 '18 at 08:41
  • @Gerhardh: i just have reference to pointer say **char* l_ptr** of m_strArry[1] in other class. If i call free(l_ptr) from that class, how can i check in main() whether m_strArry[1] is NULL or not, even its a dangling-pointer issue. – SatbirSingh Jan 15 '18 at 09:15
  • @Vilx-See my last comment for #Gerhardh posted a min ago. – SatbirSingh Jan 15 '18 at 09:16
  • @SatbirSingh - You can't. Welcome to the world of C++. :) Think of it this way - a pointer is not really much different than, say, a simple `int`. In fact, that's almost what it is behind the scenes - an integer which contains a memory address. When you pass an integer around, a copy of it is made everywhere. The same with the pointer. Passing it around copies its value (the memory address) to another unrelated variable which then lives its own life. – Vilx- Jan 15 '18 at 09:54
  • If you want to do more, you need to look at "smart pointers" which are basically classes that wrap a pointer and offer extra services, such as reference counting or something. There are many different existing implementations of smart pointers, or you can even roll out your own (but beware, it's tricky to get right). – Vilx- Jan 15 '18 at 09:58
  • [The values *are* documented](https://stackoverflow.com/a/370362/597607), but only for single compiler, and only in debug mode. – Bo Persson Jan 15 '18 at 12:33