Let's assume that, we have a C API exposed by a C++ library where the C client queries a value by passing a void pointer and a key.
bool GetValue(const char* key, void* val) {
if(val != NULL) {
// find the value using the key with some logic of library
// lets assume found value is a int
int foundValue = 34;
*(int*)val = foundValue;
return true; // or false if key not found
}
return false;
}
The C client and the C++ library developers have an agreement about the size of values associated with keys.
Let's assume the C++ library only has int and long long int, and the C client also knows it.
So the C client is expected to behave as follows when the value associated with "some_key" is an int:
int valueHolder;
if(GetValue("some_key",&valueHolder)) {
// do something with valueHolder
}
But the C client can cause stack memory corruption by providing pointer which points to less space. For example, if the C client provides a pointer which points to an unsigned char and the value written by the C++ library is int, stack memory corruption can happen.
So the C client should take proper action to avoid such a situation. My question is, how the C++ library can handle such memory corruption/crash situation and be robust to crash or memory corruption? (a small note: a template or function overload is not an option for me because C++ library can not expose such feature to a C client).
Simply you have to design API in such way that type of the value is clear.
So for example:
bool GetIntValue(const char* key, int* val) {
if(val != NULL && IsIntValue(key)) {
// find the value using the key with some logic of library
// lets assume found value is a int
int foundValue = 34;
val = foundValue;
return true;
}
return false;
}
bool GetSizeValue(const char* key, size_t* val) {
if(val != NULL && IsSizeValue(key)) {
// find the value using the key with some logic of library
// lets assume found value is a int
size_t foundValue = 12;
val = foundValue;
return true;
}
return false;
}
...
Or other way:
enum Types {
Int,
Size,
....
};
struct Variant {
enum Types type;
union {
int integer;
size_t size;
....
};
};
bool GetVariantValue(const char* key, struct Variant* val) {
if(val != NULL) {
...
*val = MakeIntVariant(33);
return true;
}
return false;
}
Unfortunately it cannot be made robust, see this link:
Checking if a pointer is allocated memory or not
You can catch the crash however using something like
try {} catch (...) {}
but there is no guarantee it will crash, and in fact it is very likely to instead overwrite/corrupt adjacent memory.
Related
This is very subjective question. I'm trying to write a logic "set null or use index argument". And I came up with the idea of additional bool argument or using negative index argument for set null condition. I wonder which one would be better.
For example, if there is a class member function as below,
bool DoSomething(bool bSetNull, unsigned int unIndex)
{
bool bReturn = false;
if (bSetNull)
{
m_pObject = nullptr;
}
else
{
m_pObject = m_pArr[unIndex]; // m_pArr could be replaced by something like m_map.find(unIndex)
bReturn = true;
}
return bReturn;
}
vs.
bool DoSomething(int nIndex)
{
bool bReturn = false;
if (nIndex < 0)
{
m_pObject = nullptr;
}
else
{
m_pObject = m_pArr[unIndex]; // m_pArr could be replaced by something like m_map.find(unIndex)
bReturn = true;
}
return bReturn;
}
Actually, the former is bothering due to additional bool argument and the latter is bothering due to use of signed type of index argument.
Please give me advice if there is better option.
In standard C there are some examples of the signed int usage like int snprintf return the length or a negative error code.
Because of the long history of C this is not a qualitative argument, but this option will not come as surprise.
However better use an std::optional field (for instance) and two functions with and without index. That is not tweaking semantics: the meaning of things.
Currently I working on a existing project (DLL ) which I have to extend.
For the transport through the DLL I have a struct for example 'ExternEntry'
and a struct which passes a array of it.
struct ExternEntry
{
unsigned int MyInt;
const wchar_t* Text;
}
struct ExternEntries
{
const ExternEntry* Data;
const unsigned int Length;
ExternEntries(const ExternEntry* ptr, const unsigned int size)
: Data(ptr)
, Length(size);
{
}
}
In the existing project architecture, it will be the first time that a array is passed to the DLL callers. So the existing architecture doesn't allow arrays and if a struct is passed to a caller, normally there is a wrapper-struct for it (because of their str pointers).
Inside the DLL I need to wrap the ExternEntry so have a valid Text pointer.
struct InternEntry
{
ExternEntry Data;
std::wstring Text;
inline const ExternEntry* operator&() const { return& Data }
UpdateText() { Data.Text = Text.c_str(); }
}
struct InternEntries
{
std::vector<InternEntry> Data;
operator ExternEntries() const
{
return ExternEntries(Data.data()->operator&(), Data.size());
}
}
So the problem is, when the Caller received the ExternEntries and created a vector again:
auto container = DllFuncReturnInternEntries(); // returns ExternEntries
std::vector<ExternEntry> v(container.Data, container.Data + container.Length);
The first element is valid. All other elements are pointing to the wrong memory because in memory the InternEntry (with the wstring Text) is stored between the next InternEntry.
Maybe I'm wrong with the reason why this can't work.
[Data][std::wstring][Data][std::wstring][Data][std::wstring]
Caller knows just about the size of the [Data]
So the vector is doing the following:
[Data][std::wstring][Data][std::wstring][Data][std::wstring]
| | |
Get Get Get
instead of
[Data][std::wstring][Data][std::wstring][Data][std::wstring]
| | |
Get Get Get
Do I have any possibilities to customize how the vector stores InternEntry objects in memory?
like Data,Data,Data ..anywhere else wstring,wstring,wstring
I hope I have explained my problem well
I am currently working on an dynamic memory container.
Basic idea of the class is that you should be able to get the iterator of an object if you really do not know it, without the use of a for loop throughout all the elements to boost performance. The issue I have is the following; when you pass your pointer address to the object you want to get the iterator of it type casts the object into the extended memory containers structures type. This type contains an extra element, an integer. (IteratorNum)
When following the code the integer within the function is set to correct value, as below would be 50. But when the returned value is set into the local integer used in the main function it is 200? I've been adding watches and cannot figure out how it is possible that the function returns 50 but value gets set to 200.
template <typename DataType> class MemoryContainer {
public:
struct LevelData : DataType
{
int element;
};
DataType &New()
{
elements++;
//Reallocate the size of the array
ld = (LevelData*)realloc(ld, sizeof(LevelData) * elements);
//Set the iteratorNumber
ld[elements - 1].element = elements - 1;
return ld[elements - 1];
}
DataType *reserve(int num)
{
return calloc(num, sizeof(DataType));
}
DataType &operator[](int i)
{
return ld[i];
}
bool inArray(DataType *type)
{
//Compare memory addresses and see if it's within.
return (type >= &ld[0]) && (type < &ld[elements - 1]);
}
static unsigned int getIterator(DataType *type)
{
// v this is 50, but in main says returns 200.
return ((LevelData*)type)->element;
}
MemoryContainer()
{
elements = 0;
}
~MemoryContainer()
{
free(data);
}
private:
unsigned int elements;
LevelData *ld;
};
struct Effective
{
//Set it to polymorphic classes
virtual void dummy()
{
}
char * testvar;
Effective(char * c)
{
testvar = c;
}
Effective(){}
};
MemoryContainer<Effective> myContainer;
int _tmain(int argc, _TCHAR* argv[])
{
//Create 200 elements in the array
for(int i = 0; i < 200; i++)
myContainer.New().testvar = "E";
//Add pointer for testing purposes to get the iterator.
Effective * pointer = &myContainer[50];
//Test setting it's value
pointer->testvar = "HEHEHE";
//Get iterator of our pointer in the array
unsigned int i = myContainer.getIterator(pointer);
printf(pointer->testvar);
system("PAUSE");
return 0;
}
I suspect it is the visual studio debugger getting confused between your two i variables. If you print out the value of i, it will print correctly. If you change the name of your variable to something else, the value shows as 50 in the debugger.
That said, your code is a mish-mash of c and c++ and won't work correctly with anything that requires a copy constructor. I would suggest at the very least using new [] rather than realloc.
Also, any user of this collection who tries to store a class with a member variable called element is going to get mighty confused.
The unsigned int i in the main function really has a value of 50, but the debugger is confusing it with the i declared in the for loop (I reproduced this with Visual Studio 2013). If you cout i it will be 50, and if you change the variable name it will show up as 50 in the debugger. I've never seen this problem before so I wonder if it might be due to your use of malloc/realloc/free with C++ objects.
Problem: I need to write/read objects from a file.This because I need to write/read a std::list to file, but in whatever case.Not only with T=int (this would be simple), but with whatever parameter.
In Java with OutputFileStream and InputFileStream this was possibile, but I suppose it's just a JVM feature.
However I am trying to read/write objects to a file:
template <class T>
bool write_object(std::fstream& out, const T& object)
{
bool result=false;
char* ptr;
const unsigned long size=sizeof(object);
if(out.good())
{
result=true;
ptr=(char*)&object;
for(unsigned int i=0;i<size;i++)
{
out << *ptr;
ptr++;
}
}
return result;
}
template <class T>
bool read_object(std::fstream& in, T& object)
{
bool result=false;
T* ptr;
T swap_temp;
const unsigned long size=sizeof(object);
char temp[size];
std::streampos pos;
if(in.good())
{
pos=in.tellg();
if(pos!=-1)
{
result=true;
for(unsigned long i=0; i<size; i++)
{
if(!in.good())
{
result=false;
break;
}
else
{
in >> temp[i];
}
}
}
}
if(result==false)
{
in.seekg(pos);
}
else
{
ptr=(T*)temp;
swap_temp=*ptr;
object=swap_temp;
}
return result;
}
But I have encountered the following problems:
-sizeof operator just returns the size of all fields, it does not consider also the data pointed by internal fields;
-If in the class there is a pointer, then this pointer could point to a "wrong" memory address, (e.g.) if I use a pointer which points to a C-style string in memory, once the program ends the string is deallocated.When the instance of the program runs again,this area of memory could be anywhere.
This method is wrong because for example sizeof(string) with my compiler returns 4.
So I suppose it uses a char pointer (I am on a 32-bit machine) to point to the C-style string allocated.Probably it does not even keep trace of the length.
So if the string has 32 characters I don't notice it, it just copies the value of the pointer.
Your approach can't work since C++ doesn't know java-like techniques like reflection so you can't distinguish between pointers and other members.
What you want is called serialisazion and you can use it with libraries like Boost.Serialization (Demo).
But even then, you can't write a general function, you have to define it specifically for each object.
I keep on receiving odd unexpected values for my bool testValue. I keep receiving random numbers as I believe it is trying to access another region of memory. I predict it is how my code is setup within my testNumber() function, but I am unsure of how to solve it. This is my logic.
I have set ok to true. Now I assign the memory address of ok to pOk.
void TextBox::lengthTest(bool *pOk, int length) {
bool ok;
if (length < MAX_LENGTH) {
ok = true;
pOk = &ok;
} else {
ok = false;
pOk = &ok;
}
}
bool lengthTestBool = lengthTest(*pOk, length);
cout << lengthTestBool <<;
output:
85
You have a fundamental misunderstanding of how one uses pointers to implement reference semantics. You want to change thing that is pointed to by the pointer:
*pOK = ok;
However, C++ actually supports references semantics natively through reference types, which may be preferable:
void testNumber(bool & OK, int n)
{
OK = true;
// ...
}
Even better, though, is to simply return a bool:
bool testNumber(int n) { /* ... */ }
if (testNumber(x)) //... etc.