I'm getting a weird access violation at the end of my main whose cause I'm having some difficulties finding.
When shutting down my application I get an access violation in the following:
xdebug
// TEMPLATE FUNCTION _DebugHeapDelete
template<class _Ty>
void __CLRCALL_OR_CDECL _DebugHeapDelete(_Ty *_Ptr)
{ // delete from the debug CRT heap even if operator delete exists
if (_Ptr != 0)
{ // worth deleting
_Ptr->~_Ty();
// delete as _NORMAL_BLOCK, not _CRT_BLOCK, since we might have
// facets allocated by normal new.
free(_Ptr); // **ACCESS VIOLATION**
}
}
Stack trace:
> msvcp100d.dll!std::_DebugHeapDelete<void>(void * _Ptr) Line 62 + 0xa bytes C++
msvcp100d.dll!std::numpunct<char>::_Tidy() Line 190 + 0xc bytes C++
msvcp100d.dll!std::numpunct<char>::~numpunct<char>() Line 122 C++
msvcp100d.dll!std::numpunct<char>::`scalar deleting destructor'() + 0x11 bytes C++
msvcp100d.dll!std::_DebugHeapDelete<std::locale::facet>(std::locale::facet * _Ptr) Line 62 C++
msvcp100d.dll!std::_Fac_node::~_Fac_node() Line 23 + 0x11 bytes C++
msvcp100d.dll!std::_Fac_node::`scalar deleting destructor'() + 0x11 bytes C++
msvcp100d.dll!std::_DebugHeapDelete<std::_Fac_node>(std::_Fac_node * _Ptr) Line 62 C++
msvcp100d.dll!_Fac_tidy() Line 41 + 0x9 bytes C++
msvcp100d.dll!std::_Fac_tidy_reg_t::~_Fac_tidy_reg_t() Line 48 + 0xe bytes C++
msvcp100d.dll!std::`dynamic atexit destructor for '_Fac_tidy_reg''() + 0xf bytes C++
msvcp100d.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 415 C
msvcp100d.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 526 + 0x11 bytes C
msvcp100d.dll!_DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 476 + 0x11 bytes C
Anyone got any ideas as to what might cause this?
I read something about facets being cached not sure if thats related?
If you override the operator new and use you may meet the same cause as me.
the code may be like
#include "yournew" //override new declare ..
#include "fstream"
std::fstream f
f.open(...)
because the iostream is template so the new of _Fac_node use your operator new. but when exit, your memory pool may exit before _Fac_tidy, then when ~_Fac_tidy() run,the program crashed.
Memory corruption bugs can (obviously) cause this (and many other kinds) of failure.
Have you tried using valgrind (memcheck) or Rational Purify against this? It will probably report the problem (possibly buried in a whole lot of other information if this would be the first time you ran such a check on your code base. You will still want to devise a minimal 'main' implementation that exhibits the behaviour to run under a memory and bounds checker
$0.02
PS. just in case, memory corruption bugs usually arise
by dereferencing stale pointers (after free/delete)
by writing beyond the end of an allocated buffer
by freeing/deleting previously pointers (mostly a symptom of bad ownership tracking)
The first, accepted, response is correct, but it does not show exactly the reason and hence the way of fixing it. According to the listed part of the call stack, I've encountered into the same problem with VC++8 (MS VS 2005) but in the different case: my CLR DLL caused AV at the same point of the code.
From the listed call stack it is seen that the code of <xdebug> that is normally compiled into msvc*.dll is called but at that moment the _Ptr already has wrong value. Hence, there is some code that either already freed the object under this pointer or set an exit hook to free the uninitialized object.
If _STATIC_CPPLIB was defined, the <xdebug> code could be complied into other modules that are loaded into the application process. Then, one exit procedure of those modules could be called prior to another one in msvcp100d.dll and thus could normally free the facet object. In my case, with _STATIC_CPPLIB defined, both the modules (exe and clr dll) were compiled.
Solution for VC++8,9
Check the final compiler options in the "Command Line" section for the presence /D "_STATIC_CPPLIB". Undefining _STATIC_CPPLIB and recompiling affected modules fixes the AV at program termination.
Note on _STATIC_CPPLIB
For VC++9 _STATIC_CPPLIB, at MSDN, there is the note that
the combination of the _STATIC_CPPLIB preprocessor definition and the
/clr or /clr:pure compiler option is not supported.
And there are no mentions on _STATIC_CPPLIB for higher VS versions.
For higher VS versions and VS 10 in particular, I suppose that the code dependent on _STATIC_CPPLIB still exists. In the TS's case, if _STATIC_CPPLIB is still used in the compiler options of any TU that includes <string> or other headers including <locale>, this improper combination could lead to AV.
I believe you're experiencing the same bug I did in the MSVC10 runtime. To my understanding, it is caused by the runtime deleting a global facet when a DLL unloads, and then deleting it again when the process ends. If you link everything statically, it shouldn't happen. It also won't happen in MSVC9, either with static or shared linkage.
TLDR; used a custom Allocation class in my code which tracks all memory crated and deleted using new. Since the shutdown function for this class is called before Microsoft's CRT clean up and frees any memory created by this. I simply overrode the CRT code in locale0.cpp in my code, and commented out the loop to free CRT memory. As it's already deleted by my class.
The application is attempting to delete memory it created for wostreambuf* and ostreambuf*., in my instance as part of a lambda function.
It created the memory which got stored in __PURE_APPDOMAIN_GLOBAL static _Fac_node* _Fac_head = nullptr; to be deleted after execution of the program ends. By calling the destructor ~_Fac_tidy_reg_t() from _Fac_tidy_reg_t.
Since in my application i override the new and delete functions and manage the memory myself. The program at the end of execution automatically deletes any memory it used, so when the CRT calls this ~_Fac_tidy_reg_t() destructor the memory is already freed, however not necessarily "nullptrjust marked as unsed. When~_Fac_tidy_reg_t()attempts to cycle through the_Fac_head` the memory is already freed and therefore causes a exception.
To solve this i simply overload ~_Fac_tidy_reg_t() and commented out the code to run the loop to delete the already deleted memory address's.
#if defined(PLATFORM_WINDOWS)
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// class locale basic member functions
#include <crtdbg.h>
//#include <internal_shared.h>
#include <xfacet>
// This must be as small as possible, because its contents are
// injected into the msvcprt.lib and msvcprtd.lib import libraries.
// Do not include or define anything else here.
// In particular, basic_string must not be included here.
// This should probably go to a compiler section just after the locks - unfortunately we have per-appdomain
// and per-process variables to initialize
//#pragma warning(disable : 4073)
//#pragma init_seg(lib)
_STD_BEGIN
[[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _Xbad_alloc();
struct _Fac_node { // node for lazy facet recording
_Fac_node(_Fac_node* _Nextarg, _Facet_base* _Facptrarg)
: _Next(_Nextarg), _Facptr(_Facptrarg) {} // construct a node with value
~_Fac_node() noexcept { // destroy a facet
delete _Facptr->_Decref();
}
#ifdef _DEBUG
void* operator new(size_t _Size) { // replace operator new
void* _Ptr = _malloc_dbg(_Size > 0 ? _Size : 1, _CRT_BLOCK, __FILE__, __LINE__);
if (!_Ptr) {
_Xbad_alloc();
}
return _Ptr;
}
void operator delete(void* _Ptr) noexcept { // replace operator delete
_free_dbg(_Ptr, _CRT_BLOCK);
}
#endif // _DEBUG
_Fac_node* _Next;
_Facet_base* _Facptr;
};
__PURE_APPDOMAIN_GLOBAL static _Fac_node* _Fac_head = nullptr;
* WHILE LOOPS IS COMMENTED OUT */
struct _Fac_tidy_reg_t {
~_Fac_tidy_reg_t() noexcept { // destroy lazy facets
//while (_Fac_head != nullptr) { // destroy a lazy facet node
// _Fac_node* nodeptr = _Fac_head;
// _Fac_head = nodeptr->_Next;
// delete nodeptr;
//}
}
};
__PURE_APPDOMAIN_GLOBAL const _Fac_tidy_reg_t _Fac_tidy_reg;
#if defined(_M_CEE)
void __CLRCALL_OR_CDECL _Facet_Register_m(_Facet_base* _This)
#else // defined(_M_CEE)
void __CLRCALL_OR_CDECL _Facet_Register(_Facet_base* _This)
#endif // defined(_M_CEE)
{ // queue up lazy facet for destruction
_Fac_head = new _Fac_node(_Fac_head, _This);
}
_STD_END
#endif // PLATFORM_WINDOWS
Related
I made a custom mesh class inherited Qt3DRender::QGeometryRenderer to draw lines in Qt3D and use it in the same way as Qt3DExtras::QShpereMesh or others. Here the source( .h , .cpp )
And on test with single line creation everithing as i expected, line creates and destroy without an error. But if do test with std::vector<Qt3DCore::QEntity*> and put to it 100 Qt3DCore::QEntity* and add them line as a component i have heap error.(here test project)
Version of Qt:6.1.0.
In Visual Studio 2019 CE with DEBUG 64bit build the runtime error message is:
HEAP[QLineMesh_test.exe]: Invalid address specified to RtlValidateHeap( 0000013BF0630000, 0000013BF522D060 ) QLineMesh_test.exe has triggered a breakpoint.
and VS points to breakpoint line in file debug_heap.cpp:
// This function is provided for backwards compatibility only. It returns TRUE
// if the given block points to an allocation from the OS heap that underlies
// this CRT debug heap. Back when the CRT used its own OS heap (prior to Dev10),
// this function would thus also tell you whether the block was allocated by this
// debug heap. Now, it just tells you whether the block was allocated by some
// debug heap.
extern "C" int __cdecl _CrtIsValidHeapPointer(void const* const block)
{
if (!block)
return FALSE;
return HeapValidate(__acrt_heap, 0, header_from_block(block)); ///<-----breakpoint here on HeapValidate
}
In VS RELEASE 64bit build breakpoint is in qarraydata.h at QArrayData::reallocateUnaligned function call.
In QtCreator with MSVC2019 64bit and minGW64-bit builds program terminated after same behaviour but without such deep explanation.
May be the error happen in function which generate the vertex data of mesh and put it to QByteArray for later usage in Qt3DCore::QBuffer.The fragment code of function from here:
inline void QLineMesh::generateVertexData()
{
...
vertex_buf.clear();
vertex_buf.resize((3 + 3) * 6 * sizeof(float));
float* possitions = reinterpret_cast<float*>(vertex_buf.data());
int index = 0;
for (auto& v : vertices)
{
possitions[index++] = v.x();
possitions[index++] = v.y();
possitions[index++] = v.z();
}
};
I can`t imagene how the heap can be affected by this mesh creation class if it's just store pointers and logic to how to manage it.
UPDATE:
In Qt 5.15.2 everithing works as expected without errors. Source in question support both versions.
Related to my previous question, I assumed that memory leak occurs in std::string, but taking a deeper look, I got some strange results. Let's begin:
Consider we have a global
static volatile std::wostringstream *Log = nullptr;
and in a WriteToLog() function we have following code:
std::wostringstream* new_log = new std::wostringstream(std::ios::in | std::ios::out);
new_log->imbue(CConsumer::GetUtf8Locale());
std::wostringstream* old_log = (std::wostringstream*)Log;
while((std::wostringstream *)::InterlockedCompareExchangePointer((PVOID volatile *)&Log, new_log, (PVOID)old_log) != new_log)
{
::SleepEx(10, FALSE);
}
std::string logtext(Hooker::Utf16ToUtf8(old_log->str()));
which utilizes proprietary:
static std::locale FORCEINLINE GetUtf8Locale()
{
static std::unique_ptr<std::codecvt_utf8_utf16<wchar_t>> code_cvt(new std::codecvt_utf8_utf16<wchar_t>(std::codecvt_mode::generate_header | std::codecvt_mode::little_endian));
return std::locale(std::locale(), code_cvt.get());
}
Since log events occurs occasionally, it generates enormous memory leak (from initial 5MB/500 handles it jumps to 200MB/300,000 handles in a matter of minutes).
Previously, I assumed it's a leak in relation to std::string, but, using Visual Studio Profiler, it shows that all leaks are caused by GetUtf8Locale().
Can anybody help me with this issue?
This answer is wrong and I overlooked the "Compare" part of InterlockedCompareExchangePointer. However, I think it's a step in the right direction.
So we start with an object who's Log member points at 0x87654321. Then two threads call WriteToLog
Thread1 Thread2
...new_log=new ...
(now new_log=0x15331564)
...new_log=new ...
(now new_log=0x25874963)
...old_log=Log;
(now old_log=0x87654321)
...old_log=Log;
(now old_log=0x87654321)
InterlockedCompareExchangePointer
(now new_log=0x87654321)
(now Log=0x15331564)
InterlockedCompareExchangePointer
(now new_log=0x15331564)
(now Log=0x25874963)
...stuff... ...stuff...
delete old_log
(now 0x87654321 is deleted)
delete old_log
(now 0x87654321 is deleted TWICE!)
And the Log member points at 0x25874963, so... log 0x15331564 is leaked!
Your use of InterlockedCompareExchangePointer is incorrect. I think this is right, depending on the code you haven't shown.
std::wostringstream* new_log = new std::wostringstream(std::ios::in | std::ios::out);
new_log->imbue(CConsumer::GetUtf8Locale());
std::wostringstream* old_log = ::InterlockedExchangePointer((PVOID volatile *)&Log.get(), new_log);
std::string logtext(Hooker::Utf16ToUtf8(old_log->str()));
delete old_log;
I'm using boost 1.47 for Arm, with the Code Sourcery C++ compiler (4.5.1), crosscompiling from Windows 7 targeting Ubuntu.
When we compile the debug version (i.e. asserts are enabled), there is an assert triggered:
pthread_mutex_lock.c:62: __pthread_mutex_lock: Assertion 'mutex->__data.__owner == 0' failed.
Compiling in release mode, the assert is not triggered and the program works fine (as far as we can tell).
This is happening under a Ubuntu 10.x Arm board.
So, it appears that the pthread_mutex_lock thinks the mutex was set by a different thread than the current one. At this point in my program, we're still single threaded, verified by printing out pthread_self in main and just before the regex constructor is called. That is, it should not have failed the assertion.
Below is the snippet of code that triggers the problem.
// Set connection server address and port from a URL
bool MyHttpsXmlClient::set_server_url(const std::string& server_url)
{
#ifdef BOOST_HAS_THREADS
cout <<"Boost has threads" << endl;
#else
cout <<"WARNING: boost does not support threads" << endl;
#endif
#ifdef PTHREAD_MUTEX_INITIALIZER
cout << "pthread mutex initializer" << endl;
#endif
{
pthread_t id = pthread_self();
printf("regex: Current threadid: %d\n",id);
}
const boost::regex e("^((http|https)://)?([^:]*)(:([0-9]*))?"); // 2: service, 3: host, 5: port // <-- dies in here
I've confirmed that BOOST_HAS_THREADS is set, as is PTHREAD_MUTEX_INITIALIZER.
I tried following the debugger though boost but it's templated code and it was rather difficult to follow the assembly, but we basically die in do_assign
(roughtly line 380 in basic_regex.hpp)
basic_regex& assign(const charT* p1,
const charT* p2,
flag_type f = regex_constants::normal)
{
return do_assign(p1, p2, f);
}
the templated code is:
// out of line members;
// these are the only members that mutate the basic_regex object,
// and are designed to provide the strong exception guarentee
// (in the event of a throw, the state of the object remains unchanged).
//
template <class charT, class traits>
basic_regex<charT, traits>& basic_regex<charT, traits>::do_assign(const charT* p1,
const charT* p2,
flag_type f)
{
shared_ptr<re_detail::basic_regex_implementation<charT, traits> > temp;
if(!m_pimpl.get())
{
temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>());
}
else
{
temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>(m_pimpl->m_ptraits));
}
temp->assign(p1, p2, f);
temp.swap(m_pimpl);
return *this;
}
I'm not sure what component is actually using the mutex--does anyone know?
In the debugger, I could retrieve the address for the variable mutex and then inspect (mutex->__data.__owner). I got the offsets from the compiler header file bits/pthreadtypes.h, which shows:
/* Data structures for mutex handling. The structure of the attribute
type is not exposed on purpose. */
typedef union
{
struct __pthread_mutex_s
{
int __lock;
unsigned int __count;
int __owner;
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
I used these offsets to inspect the data in memory. The values did not make sense:
For instance, the __data.__lock field (an int) is 0xb086b580. The __count (an unsigned int) is 0x6078af00, and __owner (an int) is 0x6078af00.
This leads me to think that somehow initialization of this mutex was not performed. Either that or it was completely corrupted, but I'm leaning to missed initialization because when I linked with debug boost libraries, there was no assert.
Now, I'm assuming that whatever mutex that is being queried, is some global/static that is used to make regex threadsafe, and that somehow it was not initialized.
Has anyone encountered anything similar? Is there some extra step needed for Ubuntu to ensure mutex initialization?
Is my implementation assumption correct?
If it is correct, can someone point me to where this mutex is declared, and where it's initialization is occurring
any suggestions on further debugging steps? I'm thinking I might have to somehow download the source and rebuild with tracing in there (hoping StackOverflow can help me before I get to this point)
One of the first things to check when a really REALLY peculiar runtime crash appears in a well-known, well-tested library like boost is whether there's a header/library configuration mismatch. IMHO, putting _DEBUG or NDEBUG in headers, especially within the structures in a way that affects their binary layout, is an anti-pattern. Ideally we should be able to use the same .lib whether we define _DEBUG, DEBUG, Debug, Debug, NDEBUG, or whatever (so that we can select the .lib based on whether we want to have debug symbols or not, not whether it matches header defines). Unfortunately this isn't always the case.
I used these offsets to inspect the data in memory. The values did not make sense:
For instance, the __data.__lock field (an int) is 0xb086b580. The __count (an unsigned > int) is 0x6078af00, and __owner (an int) is 0x6078af00.
This sounds like different parts of your code have different views on how large various structures should be. Some things to check:
Is there any #define which enlarges a data structure, but is not consistently set throughout your code base? (On Windows, _SECURE_SCL is infamous for this kind of bugs)
Do you do any structure packing? If you set #pragma pack anywhere in a header and forget to unset it at the end of the header, any data structures included after that will have a different layout than elsewhere in your program.
I have a program in which, partly for informational logging, I output the names of some classes as they are used (specifically I add an entry to a log saying along the lines of Messages::CSomeClass transmitted to 127.0.0.1). I do this with code similar to the following:
std::string getMessageName(void) const {
return std::string(typeid(*this).name());
}
And yes, before anyone points it out, I realise that the output of typeinfo::name is implementation-specific.
According to MSDN
The type_info::name member function returns a const char* to a null-terminated string representing the human-readable name of the type. The memory pointed to is cached and should never be directly deallocated.
However, when I exit my program in the debugger, any "new" use of typeinfo::name() shows up as a memory leak. If I output the information for 2 classes, I get 2 memory leaks, and so on. This hints that the cached data is never being freed.
While this is not a major issue, it looks messy, and after a long debugging session it could easily hide genuine memory leaks.
I have looked around and found some useful information (one SO answer gives some interesting information about how typeinfo may be implemented), but I'm wondering if this memory should normally be freed by the system, or if there is something i can do to "not notice" the leaks when debugging.
I do have a back-up plan, which is to code the getMessageName method myself and not rely on typeinfo::name, but I'd like to know anyway if there's something I've missed.
Another solution is to correct the underlying problem. This is not really a memory leak, just a false report. The memory blocks allocated to the tyepinfo() and the name() string are assigned the wrong block type. It is probably not a good idea to "free" this memory, since an attempt will be made by the CRT to free it again. The good news is this was finally fixed in VS2012 (_MSC_VER 1700+).
Since this only applies to _DEBUG builds, the following may be a safer solution. The function _FixTypeInfoBlockUse() should be called as mentioned above just before exiting the module entry point (main, WinMain, etc.).
#if defined(_DEBUG) && (_MSC_VER >= 1000 && _MSC_VER <= 1699)
//
// Debug memory block header:
// o Borrowed from the Microsoft CRT to fix the false "memory leak" report
// when using typeinfo 'name' accessor in a _DEBUG build of the library.
//
struct _CrtMemBlockHeader
{
struct _CrtMemBlockHeader * pBlockHeaderNext;
struct _CrtMemBlockHeader * pBlockHeaderPrev;
char * szFileName;
int nLine;
#ifdef _WIN64
int nBlockUse;
size_t nDataSize;
#else
size_t nDataSize;
int nBlockUse;
#endif
long lRequest;
unsigned char gap[4];
};
static void __cdecl _FixTypeInfoBlockUse(void)
{
__type_info_node* pNode = __type_info_root_node._Next;
while(pNode != NULL)
{
__type_info_node* pNext = pNode->_Next;
(((_CrtMemBlockHeader*)pNode) - 1)->nBlockUse = _CRT_BLOCK;
if (pNode->_MemPtr != NULL)
(((_CrtMemBlockHeader*)pNode->_MemPtr) - 1)->nBlockUse = _CRT_BLOCK;
pNode = pNext;
}
}
#endif//defined(_DEBUG) && (_MSC_VER >= 1000 && _MSC_VER <= 1699)
I've just stumbled upon this issue trying to clean the log of VLD. Yes, this is a known bug, which is fixed in VC11 only. It exists in previous versions of MSVC including 2010. This bug appears only if you use MFC. If you use MFC as DLL instead of static library, the memory leak will still exist, but won't be detected.
There is a global cache of type_info names and it is not cleared (the excerpt from <typeinfo>):
struct __type_info_node {
void *_MemPtr;
__type_info_node* _Next;
};
extern __type_info_node __type_info_root_node;
The idea is to clear this cache. This function works for me:
#include <typeinfo>
void clear_type_info_cache()
{
__type_info_node* & node = __type_info_root_node._Next;
while(node)
{
if (node->_MemPtr)
{
delete node->_MemPtr;
}
__type_info_node* tempNode = node;
node = node->_Next;
delete tempNode;
}
}
Call clear_type_info_cache() before exit. You can register it with atexit
#include <cstdlib>
int WinMain(...)
{
atexit(&clear_type_info_cache);
...
}
or call it immediately before leaving WinMain
struct dummy_scope_exit
{
typedef void (*Fun)();
dummy_scope_exit(Fun f) : m_f(f) {}
~dummy_scope_exit() { m_f(); }
Fun m_f;
};
int WinMain(...)
{
dummy_scope_exit cleaner = &clear_type_info_cache;
...
}
As pointed out by Chris Parton in the comments, this appears to be a known bug, at least with the version of compiler I am using - upgrading to VC11 would correct the issue, if I were able to upgrade.
Attempting to delete the output of typeinfo::name() partially works:
std::string getMessageName(void) const
{
std::string typeStr(typeid(*this).name());
delete (typeid(*this).name());
return typeStr;
}
However there are still some memory leaks - I just noticed that previously I appeared to be getting two leaks per call (perhaps due to the classes being inside a namespace?). Using the above version of code, this went down to one leak per call.
Another solution that appears to work is to link in the dynamic version of the MFC libraries (yes, I'm using MFC, don't judge me), rather than the static version.
VS stores type info in a singly-linked list. The header of this list is accessible by an opaque structure accessible by name __type_info_root_node. Actually it is a SLIST_HEADER structure.
Win32 API has a set of concurrency-safe function to work with such structures.
To fix memory leaks report In your case you need to delete all nodes of this list.
#include <Windows.h>
#include <typeinfo>
#include <vld.h>
void ClearTypeinfoCache()
{
#ifdef _DEBUG
while (auto entry = InterlockedPopEntrySList(reinterpret_cast<PSLIST_HEADER>(&__type_info_root_node)))
{
free(entry);
}
#endif
}
int main()
{
atexit(ClearTypeinfoCache);
return 0;
}
Updated: VLD 2.5.1 does not report memory leaks on type_info::name() in VS2015 Update 3.
I have a very simple class that looks as follows:
class CHeader
{
public:
CHeader();
~CHeader();
void SetCommand( const unsigned char cmd );
void SetFlag( const unsigned char flag );
public:
unsigned char iHeader[32];
};
void CHeader::SetCommand( const unsigned char cmd )
{
iHeader[0] = cmd;
}
void CHeader::SetFlag( const unsigned char flag )
{
iHeader[1] = flag;
}
Then, I have a method which takes a pointer to CHeader as input and looks
as follows:
void updateHeader(CHeader *Hdr)
{
unsigned char cmd = 'A';
unsigned char flag = 'B';
Hdr->SetCommand(cmd);
Hdr->SetFlag(flag);
...
}
Basically, this method simply sets some array values to a certain value.
Afterwards, I create then a pointer to an object of class CHeader and pass it to
the updateHeader function:
CHeader* hdr = new CHeader();
updateHeader(hdr);
In doing this, the program crashes as soon as it executes the Hdr->SetCommand(cmd)
line. Anyone sees the problem, any input would be really appreciated
When you run into a crash, act like a crime investigator: investigate the crime scene.
what is the information you get from your environment (access violation? any debug messages? what does the memory at *Hdr look like? ...)
Is the passed-in Hdr pointer valid?
Then use logical deduction, e.g.:
the dereferencing of Hdr causes an access violation
=> passed in Hdr points to invalid memory
=> either memory wasn't valid to start with (wrong pointer passed in), or memory was invalidated (object was deleted before passing in the pointer, or someone painted over the memory)
...
It's probably SEGFAULTing. Check the pointers.
After
your adding some source code
your comment that the thing runs on another machine
the fact that you use the term 'flag' and 'cmd' and some very small datatypes
making me assume the target machine is quite limited in capacity, I suggest testing the result of the new CHeader for validity: if the system runs out of resources, the resulting pointer will not refer to valid memory.
There is nothing wrong with the code you've provided.
Are you sure the pointer you've created is the same same address once you enter the 'updateHeader' function? Just to be sure, after new() note the address, fill the memory, sizeof(CHeader), with something you know is unique like 0XDEAD, then trace into the updateHeader function, making sure everything is equal.
Other than that, I wonder if it is an alignment issues. I know you're using 8 bit values, but try changing your array to unsigned ints or longs and see if you get the same issue. What architecture are you running this on?
Your code looks fine. The only potential issue I can see is that you have declared a CHeader constructor and destructor in your class, but do not show the implementation of either. I guess you have just omitted to show these, else the linker should have complained (if I duplicate this project in VC++6 it comes up with an 'unresolved external' error for the constructor. It should also have shown the same error for the destructor if you had a... delete hdr; ...statement in your code).
But it is actually not necessary to have an implementation for every method declared in a class unless the methods are actually going to get called (any unimplemented methods are simply ignored by the compiler/linker if never called). Of course, in the case of an object one of the constructor(s) has to be called when the object is instantiated - which is the reason the compiler will create a default constructor for you if you omit to add any constructors to your class. But it will be a serious error for your compiler to compile/link the above code without the implementation of your declared constructor, so I will really be surprised if this is the reason for your problem.
But the symptoms you describe definitely sounds like the 'hdr' pointer you are passing to the updateHeader function is invalid. The reason being that the 1st time you are dereferencing this pointer after the updateHeader function call is in the... Hdr->SetCommand(cmd); ...call (which you say crashes).
I can only think of 2 possible scenarios for this invalid pointer:
a.) You have some problem with your heap and the allocation of memory with the 'new' operator failed on creation of the 'hdr' object. Maybe you have insufficient heap space. On some embedded environments you may also need to provide 'custom' versions of the 'new' and 'delete' operator. The easiest way to check this (and you should always do) is to check the validity of the pointer after the allocation:
CHeader* hdr = new CHeader();
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
The normal behaviour when 'new' fails should actually be to throw an exception - so the following code will cater for that as well:
try{
CHeader* hdr = new CHeader();
} catch(...) {
//handle or throw specific exception i.e. AfxThrowMemoryException() for MFC
}
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
}
b.) You are using some older (possibly 16 bit and/or embedded) environment, where you may need to use a FAR pointer (which includes the SEGMENT address) for objects created on the heap.
I suspect that you will need to provide more details of your environment plus compiler to get any useful feedback on this problem.