What is wrong with this void pointer to struct cast? [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
The task here is to call out everything that is wrong with this snippet. I do not know if the code is being presented as C or C++, so either assumption is valid and helpful.
struct MyStructData
{
VOID* pPtr;
UINT32 flags;
}
VOID main()
{
MyStructData* pMyStructData = InitFunction();
// work done here
DeInitFunction(pMyStructData);
}
MyStructData* InitFunction()
{
MyStructData* pMyStructData = malloc(sizeof(MyStructData));
pMyStructData->pPtr = malloc(1024);
return pMyStructData;
}
VOID DeInitFunction(MyStructData* pMyStructData)
{
free(pMyStructData);
}
I see the void pointer is declared, then in InitFunction, pMyStructData has malloc with size of the struct MyStructData. Next the pPtr member is accessed and malloc-ed a big chunk (1024)... this is where I see an issue. Since the pPtr member was declared as void, pMyStructData is too small to allocate 1024 bytes?
Please help me to understand what is happening here, and what I missed.

Answer was provided before language tag was changed from C to C++.
struct MyStructData
{
VOID* pPtr;
UINT32 flags;
}
There are no types VOID or UINT32 in C unless you include some headers providing them. Maybe some Windows stuff?
Also a ; is missing after that struct declaration. (Thanks to wildplasser)
VOID main()
Valid signatures for main are int main(void) or int main (int argc, char *argv[]) or compatible.
{
MyStructData* pMyStructData = InitFunction();
There is no type MyStructData. Use struct MyStructData or add a typedef.
You do not provide a prototype for InitFunction().
// work done here
DeInitFunction(pMyStructData);
}
Same here: No prototype for DeInitFunction
MyStructData* InitFunction()
{
MyStructData* pMyStructData = malloc(sizeof(MyStructData));
Again: Use struct MyStructData.
Use of malloc without prototype. Include proper headers.
pMyStructData->pPtr = malloc(1024);
Basically valid (except for missing prototype), but you should check if pMyStructData is NULL before dereferencing it.
return pMyStructData;
}
VOID DeInitFunction(MyStructData* pMyStructData)
{
free(pMyStructData);
}
As Johnny Mopp mentioned, pMyStructData->pPtr is not freed causing a memory leak.
Again: No type VOID and MyStructData.
Again: Use of function (free) without prototype.
Now regarding your findings:
I see the void pointer is declared, then in InitFunction, pMyStructData has
malloc with size of the struct MyStructData.
Apart from the issues I mentioned abov, that is fine. That is how allocating memory for structs is don.
Next the pPtr member is accessed and malloc-ed a big chunk (1024)... this
is where I see an issue. Since the pPtr member was declared as void,
pMyStructData is too small to allocate 1024 bytes?
That is no issue. The member ptr points to some memory provided by malloc There is no relation to the struct where the pointer itself resides. It does not need to fit into the struct.
You only should check for NULL before this.

Related

conversion from void pointer to pointer to struct or class

what is the correct approach for converting void * to pointer to struct or class.
sometime mistakes can happen like pointer to different class or struct was assigned.how to catch these types of mistakes over compile or run time.
following program tried, surprisingly it compiled and no crash even after execution.
what is right way for type casting from void * to pointer to struct or class in cpp
Description:
how to avoid type casting related issues from void * to pointer to class or struct at compile time or runtime. if static_cast is used for conversion from void * then code is compiled, even it is invalid conversion.
#include <iostream>
using namespace std;
struct stu
{
int x;
int y;
int z;
};
struct clg
{
int x;
float y;
char z;
};
void fun(void *msg)
{
clg *myclg = static_cast<clg*>(msg);
cout<<"casting is done."<<endl;
}
int main()
{
stu* st = new stu();
clg* cl = new clg();
void *ptr = st;
fun(ptr);
return 0;
}
You can't type check a void pointer. It points to a memory address but you are responsible for managing the size of the memory chunk it points to. In other words, void* doesn't give more information than : this is a memory address. Compare to a char* that holds the information : this is a memory address and from this address to the next 7 bits address, is one chunk of data. Now, that's very unsafe, but in most cases, you shouldn't find yourself using one (unless you're coding legacy c++ but given the c++14 tag, I reckon it isn't the case).
void* was used to implement generic functions in case you didn't know the type of data that was going to be used. There are essentially two solutions to get around it : heritage and templates.
There are cases when you will have to use void pointers. One of them would be when interfacing with C code as C will only take generic pointers. Another use case would be when you don't care about the data format (memcpy for exemple). But then, no type casting is needed here.

What is the best memory management for GCC C++? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
What's the problem of my memory management? Because it causes crash that I show in a comment in the code below ("A memory block could not be found when trying to free."). I know that my memory management is not thread safe because I use global variables g_numBlocks and g_blocks that can cause risk when using multiple threads.
Since my memory management code seems too complex, can anyone suggest a stable and better "Memory Management for C++" to avoid memory leaks.
The code that contains bug
#include "emc-memory.h" // <-- Declare the functions MALLOC() and FREE() from other library.
#include <vector>
int main() {
printf("HERE(1)\n");
{
std::vector<string> paths = { // <-- Problem, 'std::vector' & 'string' use internal malloc/free & operator new/delete that are overwritten with my own custom memory management.
"/foo/bar.txt",
"/foo/bar.",
"/foo/bar",
"/foo/bar.txt/bar.cc",
"/foo/bar.txt/bar.",
"/foo/bar.txt/bar",
"/foo/.",
"/foo/..",
"/foo/.hidden",
"/foo/..bar",
};
} // <-- It crashes here, error in FREE(): "A memory block could not be found when trying to free.".
printf("HERE(2)\n"); // The reason I know it crashes above is this line is not evaluated, only "HERE(1)" is printed. I'm using [RelWithDebInfo] with blurry debugging info.
return 0;
}
Compilers:
[Visual Studio 2015] [Debug]: No problem.
[Visual Studio 2015] [RelWithDebInfo]: No problem.
[GCC 12.1.0 x86_64-w64-mingw32] [Debug]: No problem.
[GCC 12.1.0 x86_64-w64-mingw32] [RelWithDebInfo]: Broken which means there's a bug.
In "emc-memory.h" in other library .so file
extern const char* __file;
extern int __line;
#define new (__file = __FILE__, __line = __LINE__, 0) ? 0 : new
enum MEMORYBLOCKTYPE {
MEMORYBLOCKTYPE_MALLOC,
MEMORYBLOCKTYPE_NEW,
};
void *MALLOC(size_t size, MEMORYBLOCKTYPE type);
void *REALLOC(void *block, size_t newSize);
void FREE(void *block, MEMORYBLOCKTYPE type);
#define malloc(size) ((__file = __FILE__, __line = __LINE__, 0) ? 0 : MALLOC(size, MEMORYBLOCKTYPE_MALLOC))
#define realloc(block, newSize) REALLOC(block, newSize)
#define free(block) FREE(block, MEMORYBLOCKTYPE_MALLOC)
In "emc-memory.cpp" in other library .so file
I use this code in a link to override the operator new & delete: https://codereview.stackexchange.com/questions/7216/custom-operator-new-and-operator-delete
typedef unsigned long long BlockId; // The reason it's 64-bit is a memory block can be freed and reallocated multiple times, which means that there can be a lot of ids.
BlockId g_blockId = 0;
BlockId newBlockId() {
return g_blockId++;
}
struct Block {
const char *file;
int line;
const char *scope;
char *hint;
size_t size;
BlockId id; // That id is used for comparison because it will never be changed but the block pointer can be changed.
void *block;
MEMORYBLOCKTYPE type;
};
bool g_blocks_initialized = false;
int g_numBlocks;
Block **g_blocks;
void *MALLOC(size_t size, MEMORYBLOCKTYPE type) {
if (g_blocks_initialized == false) {
g_blocks_initialized = true;
_initializeList(g_numBlocks, g_blocks);
}
Block *b = (Block *)malloc(sizeof(*b));
b->file = __file ; __file = nullptr;
b->line = __line ; __line = 0;
b->scope = __scope; __scope = nullptr;
b->hint = allocateMemoryHint(__hint);
b->size = size;
b->id = newBlockId();
b->block = malloc(size);
b->type = type;
_addListItem(g_numBlocks, g_blocks, b);
return b->block;
}
void FREE(void *block, MEMORYBLOCKTYPE type) {
if (block == nullptr) {
return; // 'free' can free a nullptr.
}
for (int i = 0; i < g_numBlocks; i++) {
Block *b = g_blocks[i];
if (b->block == block) {
if (b->type != type) {
switch (type) {
case MEMORYBLOCKTYPE_MALLOC: EMC_ERROR("The memory block type must be MALLOC."); break;
case MEMORYBLOCKTYPE_NEW: EMC_ERROR("The memory block type must be NEW."); break;
default: EMC_ERROR("Error"); break;
}
}
_removeListItem(g_numBlocks, g_blocks, b);
freeMemoryHint(b->hint); b->hint = nullptr;
SAFE_FREE(b->block);
SAFE_FREE(b);
return;
}
}
EMC_ERROR("A memory block could not be found when trying to free.\n\nExamples:\n - Calling free(pointer) where pointer was not set to zero after it's been called twice, the solution was to use SAFE_FREE(). And if possible, replace any free() with SAFE_FREE(). For example, see Lexer::read0() on the original line \"free(out.asIdentifier);\".\n - If an 'Engine' object is destroyed before destroying a Vulkan object then it can cause this error (It can happen with 'Release' or 'RelWithDebInfo' configuration but not with 'Debug' configuration), that problem happened to me and I stuck there for hours until I realized it.");
}
I would humbly suggest that without a very clear reason to think otherwise the best memory management for GCC C++ is the out-of-the-box default memory management for GCC C++.
That would mean your best solution would have been to do nothing or as it is now strip out your overrides of the global operators.
You may find in some area of a system the default memory management is sub-optimal but in 2022 the default options are very effective and if you find a general purpose strategy that is better it's a publishable paper.
However your question tells us nothing about the application in question or your motivations for thinking you should even try to change the memory management let alone give advice on what to.
Sure you can add a global allocation mutex to block memory management and make it thread-safe. I will be surprised if that doesn't turn out to more than throw away whatever advantage you're hoping to gain.
Not sure where SAFE_FREE is coming from.
If you see in MALLOC function, they use c runtime malloc. Meaning that if you want to free the block you need to use the corresponding free() function.
Make sure that SAFE_FREE is indeed using the c runtime free with the correct parameters.

How to make function return pointer to an array or object in C++?

I'm confused with a lot of answers found about what is a simple thing in other languages. I would like to get a reference to an object contained in class or struct. I've come up to using one of two different functions (here - getData()).
Question:
So, I am not sure which one to use, they appear to do the same thing. Other thing, is there some reason I should care because it's a union? And the most important question here is - I'm not sure about delete part I found in some answers, which scares me that this code example I've shown is not complete and will cause some memory leaks at some point.
#include <iostream>
#include <stdint.h>
using namespace std;
class settings_t {
private:
static const long b1 =0;
uint8_t setmap;
public:
uint8_t myBaseID;
uint8_t reserved1;
uint8_t reserved2;
};
class test1 {
public: //actually, I want this to be private
long v1;
settings_t st;
union {
uint8_t data[4];
uint32_t m1;
settings_t st1;
};
public:
uint8_t * getData() {
return data;
}
uint8_t (&getData2())[4] {
return data;
}
};
int main() {
test1 t1;
t1.data[2]=65;
uint8_t *d1 = t1.getData();
cout<<" => " << d1[2];
d1[2]=66;
uint8_t *d2 = t1.getData2();
cout<<" => " << d2[2];
}
The main difference of c++ from languages like c# or java is that it does not provide you with built in memory management (not a managed language). So, if the program allocates memory in c++, it is a responsibility of the program to release the memory when it is not needed. so, delete in your answers is based on this requirement.
However in you case, the getData() function returns a pointer to the data which is a part of the class test1. This is an array and the array will exist as long as the object of this class exist. Both versions of the getData will work.
You did not use any dynamic data allocation, the object t1 of type test1 was allocated on the stack of the main function and would exist till your program exits. You should not worry about 'delete'.
The difference between two methods you use is that the first method does not care about the array size it returns, whether the other does. For that reason the second methods has very limited practical use, but provides better syntactic checking.

function pointer addressing functions with multiple arguments [duplicate]

This question already has answers here:
Function pointer to different functions with different arguments in C
(6 answers)
Closed 9 years ago.
is there any possibility for function pointer for addressing function with different no of arguments of same return type, if not any alternate would be helpful.. thanks in advance
example:
struct method
{
char *name;
void (*ptr)(?); //? : what to define as arguments for this
};
void fun1(char *name)
{
printf("name %s\n\r",name);
}
void fun2(char *name, int a)
{
printf("name %s %d\n\r",name,a);
}
//defined before main()
method def[]=
{
{"fun1",fun1},
{"fun2",fun2}
}
//some where in main()
//call for function pointer
def[1].ptr("try", 2);
typedef void (*myfunc)(char *,int);
struct method
{
char *name;
myfunc ptr;
};
method def[]=
{
//we store fun1 as myfun
//type void(char*,int) and use it this way
{"fun1",(myfunc)fun1},
{"fun2",fun2}
};
This is by theory undefined behavior, but in reality it should work on most platforms
* edit -> this works on all plaforms just like printf(const char*,...) does.
In C, you can make your function pointer declaration read
void (*ptr)();
Which means 'A pointer to a function returning void and expecting an unspecified number of argments.'
With that adjustement, your sample program works as expected to me. However, it may well be that you're venturing into undefined (or at least implementation defined) lands here - I don't know for sure and I'm not a language lawyer (however there are plenty of language lawyers frequenting SO, so I'm sure somebody can whip up the relevant section of the standard or prove that there is none). So maybe you should rather use
/* Here be dragons! */
void (*ptr)();
instead.
Solution #1:
void fun1(char *name, ...);
void fun2(char *name, ...);
Solution #2:
method def[]=
{
{"fun1",printf},
{"fun2",printf}
}

duplicate typedef struct through pointer

I have following typedef defined and *ButtonSettingPtr as a pointer:
typedef struct
{
void *next;
char** buttonsetting;
char* currentsetting;
uint16_t presetid;
uint16_t currentcounter;
uint16_t maxsize;
uint16_t buttonid;
} ButtonSetting;
typedef ButtonSetting *ButtonSettingPtr;
class Options {
private:
ButtonSettingPtr settings;
ButtonSettingPtr preset1;
public:
Options();
void newSetting(char** _setting, uint16_t _maxsize, uint16_t _buttonid);
// some other stuff defined here
}
With the newSetting() function I am adding several new entries to my
typedef instance! Now, I would like to save all these settings
(this->settings) into another pointer (this->preset1) via memcpy to
later call them up again via another function, since I am using
this->settings in a couple of other functions (getCurrentSetting) which
are working quite well etc.
char *Options::getCurrentSetting(uint16_t _buttonid) {
ButtonSettingPtr setting = (ButtonSettingPtr)this->settings;
while (setting != NULL)
{
if (setting->buttonid == _buttonid) {
char * tmpsetting =
setting->buttonsetting[setting->currentcounter];
return tmpsetting;
}
setting = (ButtonSettingPtr)setting->next;
}
return NULL;
}
Here's the problem:
void Options::savePreset() {
memcpy(&this->preset1,&this->settings,sizeof(&this->settings));
}
void Options::loadPreset() {
memcpy(&this->settings,&this->preset1,sizeof(&this->preset1));
}
It seems that my preset1 pointer is always exactly the same as
this->settings even though i am changing settings inbetween. I
understand that with the &amp sign it literally copies the address of
that pointer, so to no surprise they will both always be exactly the
same. But what I would like to copy is rather all bytes and point them
to preset1, so I can recall all the settings later again.
So, without the &amp sign my code just hangs:
void Options::savePreset() {
memcpy(this->preset1,this->settings,sizeof(this->settings));
}
void Options::loadPreset() {
memcpy(this->settings,this->preset1,sizeof(this->preset1));
}
Do I have to malloc the this->preset1 pointer before I memcpy everything
to it? The whole code is compiled using avr-libc for an atmega chip.
Thanks in advance for any useful hint!
ps: My understanding of C++ has been surely better when I was younger!
It looks like you're doing a home-grown singly linked list. If you replace that with std::vector you'll find that copying one to the other is as easy as preset1 = settings; (you don't need to put this-> in front of everything unless you just prefer that style).
You might also want to replace the char** inside the class with std::vector<string> as well, then the actual strings will be copied.
Yes, you do need to malloc preset1 (no need to dereference it with this-> inside a member function. If you want to make it clear that it's a class data member, name it m_preset1 or mPreset1 as you like).
So, in your constructor set preset1 to NULL. Then in your member function you can:
void Options::savePreset() {
if (preset1 == NULL) {
preset1 = (ButtonSettingPtr)malloc(sizeof (ButtonSetting));
}
memcpy(preset1, settings, sizeof(ButtonSetting));
}
Don't forget to add error checking. But really, I don't see any reason not to statically allocate space instead and avoid memory allocation issues:
class Options {
private:
ButtonSetting settings;
ButtonSetting preset1;
public:
Options();
void newSetting(char** _setting, uint16_t _maxsize, uint16_t _buttonid);
// some other stuff defined here
}
void Options::savePreset() {
memcpy(&preset1, &settings, sizeof(ButtonSetting));
}
Note that sizeof(this->settings) will always be 4 or 8 (depending on 32 or 64 bit CPU) because you're asking for the size of a pointer, not the size of the structure.
sizeof(&this->settings)
will return the size of a pointer because it is effectively a pointer.
sizeof(this->settings)
will return the size of a pointer because it is a pointer.
sizeof(*this->settings)
will return the size of the anonymous struct that settings points too.
And as for the question of needing to malloc space for
this->preset1
depends on you code. But it for sure needs to point to valid memory!