EDIT: Dear Future Readers, the std::string had nothing to do with the problem. It was an unterminated array.
In a nutshell, the problem is that adding a declaration of a single std::string to a program that otherwise contains only C causes the error "Access violation reading location 0xfffffffffffffffe."
In the code below, if the line where the std::string is declared is commented out, the program runs to completion without error. If the line however is left in the program (uncommented), the program crashes with the above stated Acess Violation error. When I open the running program in the VS2010 debugger, the Access Violation has occurred at the call to ldap_search_sA().
Notice that the declared std::string is never used. It doesn't have to be used for it to cause the access violation. Simply declaring it will cause the Access Violation.
My suspicion is it has nothing to do with the LDAP code, but I could be wrong.
int main()
{
try {
// Uncommenting the next line causes an Access Violation
// at the call to ldap_search_sA().
// std::string s;
LDAP* pLdapConnection = ldap_initA("eu.scor.local", LDAP_PORT);
ULONG version = LDAP_VERSION3;
ldap_set_option(pLdapConnection, LDAP_OPT_PROTOCOL_VERSION, (void*) &version);
ldap_connect(pLdapConnection, NULL);
ldap_bind_sA(pLdapConnection, NULL, NULL, LDAP_AUTH_NTLM);
LDAPMessage* pSearchResult;
PCHAR pMyAttributes[2];
pMyAttributes[0] = "cn";
pMyAttributes[1] = "description";
ldap_search_sA(pLdapConnection, "dc=eu,dc=scor,dc=local", LDAP_SCOPE_SUBTREE, "objectClass=computer)", pMyAttributes, 0, &pSearchResult);
} catch (...) {
printf("exception\n");
}
return 0;
}
PCHAR pMyAttributes[2];
pMyAttributes[0] = "cn";
pMyAttributes[1] = "description";
Attribute array should be NULL-terminated:
PCHAR pMyAttributes[3];
pMyAttributes[0] = "cn";
pMyAttributes[1] = "description";
pMyAttributes[2] = NULL;
I don't know what ldap_search_sA is, but the ldap_search function in
OpenLDAP takes a pointer to a null pointer terminated array of char*.
The array you are passing isn't correctly terminated, so anything may
happen. I'd recommend using std::vector<char*> for this, in general,
and wrapping the calls in a C++ function which systematically postfixes
the terminator, so you don't forget. Although in such simple cases:
char* attributes[] = { "cn", "description", NULL };
will do the trick. It will probably provoke a warning; it really should
be:
char const* attributes[] = { ... };
But the OpenLDAP interface is legacy C, which ignores const, so you'd
need a const_cast at the call site. (Another argument for wrapping
the function.)
Finally, I'd strongly advise that you drop the obfuscating typedefs
like PCHAR; they just make the code less clear.
According to my experience, when weird things like this are observed in C++, what is in fact happening is that some piece of code somewhere corrupts memory, and this corruption may manifest itself in various odd ways, including the possibility that it may not manifest itself at all. These manifestations vary depending on where things are located in memory, so the introduction of a new variable probably causes things to be moved in memory just enough so as to cause a manifestation of the corruption where otherwise it would not be manifested. So, if I were in your shoes I would entirely forget about the string itself and I would concentrate on the rest of the code, trying to figure out exactly what you do in there which corrupts memory.
I notice that you invoke several functions without checking their return values, even though it is not in the spec of these functions to throw exceptions. So, if any of these functions fails, (starting with ldap_initA,) and you proceed assuming that it did not fail, you may get memory corruption. Have you checked this?
Related
I'm trying to work with a C interface generated using camlidl. The library I'm working with returns an error code by allocating and filling an in/out argument char* error_message and returning it. After the function call, I check the error code for non-zero... if true, I call caml_failwith(error_message) to throw an OCaml exception using the library error message.
However, I started digging a bit, because throwing the exception looks as though it will terminate the function and never free the error message. Consider this mock code:
/* in the C stub function call... */
double _res;
int error = 0;
char* error_message = NULL;
// if this function errors, it will set error to non-zero
// and strdup something into error_message
_res = call_library_function(&error, error_message);
if (error) {
caml_failwith(error_message);
free(error_message); // NEVER CALLED?
}
/* code to copy result to an OCaml value and return */
The exception func caml_failwith(s) implementation is in runtime/fail_*.c, but it basically just calls caml_raise_with_string, which is:
CAMLparam1(tag);
value v_msg = caml_copy_string(msg);
caml_raise_with_arg(tag, v_msg);
CAMLnoreturn;
So, it copies the string to the OCaml value with caml_copy_string, and then raises the arg and no-returns. In short, error_message is lost.
...Right? What am I missing here... I could use canned strings but that makes dynamic error messages impossible. I could maybe use static char*, though it's not thread safe any more without a bunch of work. Is there any way to call caml_failwith, using a plain old dynamic char*, and not have it cause a leak?
EDIT: I thought of one solution...
char error_message_buf[100] = {'\0'};
double _res;
// ... rest of local vars and service call ...
if (error) {
strncpy(error_message_buf, error_message, 99)
free(error_message);
caml_failwith(error_message_buf);
}
... but man that's ugly. strncpy to the stack just to turn around and caml_copy_string again? Plus, it sets a hardcoded cap on error message length. Still, if it's the only way not to leak...
caml_failwith() is designed so you can call it with a constant string, which is a very common case:
caml_failwith("float_of_string");
So, you can't expect it to free its argument.
I don't personally consider this a space leak, it's just how the function is designed.
Your solution of copying the message first seems reasonable (and not particularly ugly) to me.
(This, in essence, is why I switched from C to OCaml many years ago.)
Currently, there is one exception thrown from program written by C++, and running under windows.
here is the min dump information in the logs.
08/12/15 04:37:19 I New Information for UID 2d936a, FloorLoc F1505
08/12/15 04:37:19 E >>>>> EXCEPTION: Access Violation while trying to read address 20203567
[Fault address: 004AF945 01:000AE945 C:\Program Files (x86)\MySystems\WPR.exe 00400000] <<<<<
Call stack:
Load addr Address Frame Logical addr Module
00400000 004AF945 0588F8CC 0001:000AE945 C:\Program Files (x86)\MySystems\WPR.exe
00400000 004A89A4 0588FAEC 0001:000A79A4 C:\Program Files (x86)\MySystems\WPR.exe
According to the logical addr and .map file, I can find the codes where this exception thrown.
if (TempMSE->m_elem == NULL)
{
TempMSE->m_elem = new Element(element);
TempMSE->m_elem->SetLocation(FloorLoc);
LoggerInfo("New Information for UID %x, FloorLoc %s", Id, FloorLoc.ToString(buf));
}
TempMSE->m_elem->SetValue0(CIN_0, 0); // this exception is thrown here!!! through logical address 0001:000AE945
It seems that the m_elem gets one address from new operator, and there is NO exception for SetLocation function calling. Also the following log output correctly.
Why there is one exception thrown from SetValue0? Here is function SetValue0
void SetValue0(INDEX idx, DWORD val)
{
if (idx >= 0 && idx < MAX_INDEX){
if(val != m_Info[idx])
{
m_Info[idx] = val;
}
}
}
The m_Info is one array variable in the Element, and its size is MAX_INDEX.
On the other side, the address 0x20203567 seems one readable address, how could it be read violation?
Edit
Add more information here
class Element {
// other function here...
private:
FloorLocation m_FloorLoc;
DWORD m_Info[MAX_INDEX];
bool m_Dirty;
};
Element::Element(const Element& elem) {
m_FloorLoc = elem.m_FloorLoc;
for (int i = 0; i < MAX_INDEX; ++i)
m_Info[i] = elem.m_Info[i];
m_Dirty = elem.m_Dirty;
}
class FloorLocation {
// other function here...
private:
FloorId m_floorloc;
};
FloorLocation::FloorLocation( const FloorLocation& loc )
{
memset(&m_floorloc, ' ', 8); // space filled
if(loc.m_floorloc.id[0] != 0)
{
memcpy(m_floorloc.id, loc.m_floorloc.id, 8);
// eliminate nulls
for(int ndx=0; ndx < 8; ndx++)
{
if(m_floorloc.id[ndx] == 0)
m_floorloc.id[ndx]=' ';
}
}
}
typedef struct {
char id[8];
} FloorId;
These kinds of questions are a little hard to answer. I gave some ideas in comments, which I'll elaborate on here. Here are the kinds of things I look for when I have these sorts of crash logs with no other leads.
An access violation on read at that location suggests one of the following:
TempMSE is not a valid pointer, and the exception is thrown when attempting to get m_elem from it;
TempMSE->m_elem is not valid, and the exception is thrown inside SetValue0 when attempting to test the value of m_Info[idx].
In the latter case, this could occur if you delete TempMSE->m_elem somewhere but don't set it to NULL. If another thread is responsible for that delete, perhaps you have a race condition here where it's about to be set to NULL, but this code is executed first.
Another possibility is that either TempMSE or TempMSE->m_elem get corrupted somewhere along the way. This could be the result of a buffer overrun inside TempMSE (if you have arrays), or basically any sort of undefined behaviour that occurs near these pointers in memory. If TempMSE is on the stack, then look for any potential trouble there.
I don't want to fill this answer with other kinds of speculation (like heap corruption), but hopefully it gives you some avenues to try. The basic list of common culprits is this:
coding error (not initialising or resetting a value)
threading issues, race conditions...
undefined behaviour or overruns trashing data
Good luck!
I can't say what is actually wrong, but I would disassemble the code at 0x004AF945 - and several instructions before, and try to understand what part of the failing function that is.
As pointed out in one of the comments, the address that the fault happens at is suspiciously looking like 'C# ', which makes me think that somewhere a string is overflowing somewhere...
This is just a guess, but I suspect TempMSE->m_elem is what contains the value 0x20203567, and thus is NOT NULL when it tries to access it, meaning no logging is performed. [Obviously this is based on what code you have shown so far, and if there is logging before/after that show this is not the case, my second guess is that m_info is somehow wrong...
inside my MFC (VC2010 SP1) project, I'm widely using a third party library to write some data in a database. This library is quite old (I've found it compiled for VS2005) and uses _variant_t to handle data.
In a particular case anyway I get a strange behaviour, I'll try to explain it:
// .h
struct myData
{
blastuff
CString strMyCode;
};
class MyClass
{
protected:
myData m_Foo;
};
// .cpp
// In OnInitDialog:
//...
TrdPartRecordset *pRS;
//...
pRS->GetFieldValue( _T("MyDBColumn"), m_Foo.strMyCode );
Now, I do my job and when user press OK, it's time to save to database and here start the problems:
// In OnOK
TrdPartRecordset *pRS;
//...
pRS->SetFieldValue( _T("MyDBColumn"), m_Foo.strMyCode );
Problem: if I do not modify m_Foo.strMyCode, I don't have any problem. What if I modify it? Well, if m_Foo.strMyCode does NOT contain ANY number, still have no problem.
Instead, when I have a number, I get a nasty error:
Unhandled exception at 0x77772d37 in Mosaico.exe: 0xC0000005: Access violation reading location 0x9d7077b7.
which is an attempt to read a deleted location. I've checked m_Foo in the watch and it's correct and valid, so I've digged into library source code:
BOOL TrdPartyRecordset::SetFieldValue(LPCTSTR lpFieldName, CString strValue)
{
_variant_t vtFld;
if(!strValue.IsEmpty())
vtFld.vt = VT_BSTR;
else
vtFld.vt = VT_NULL;
vtFld.bstrVal = strValue.AllocSysString();
BOOL bret = PutFieldValue(lpFieldName, vtFld);
SysFreeString(vtFld.bstrVal);
return bret;
}
What it happens is that vtFld is valid until SysFreeString and it get destroyed after it (I can see it proceding step-by-step with debugger), but ONLY WHEN I HAVE NUMBERS INTO strValue. This doesn't happen when strValue is pure alphabetical.
I've searched around the Internet and found that this kind of error happens when you double release a resource and so I've commented out SysFreeString and boom goes the dynamite: no more crashes.
Anyway is a better programmer than me so I guess that if he put that SysFreeString he had his reasons, moreover, this is the only part of my program where this mechanism crashes.
My question is: do I lose memory commenting out that SysFreeString?
Another one: do you have better solutions?
The reason is simple:
The memory is freed twice!
_variant_t has a destructor. Set the type to VT_BSTR. You also see the pojnter and type to VT_BSTR
After the function you call, you free the memory again and the destructor does the same.
The code should look like this:
_variant_t vtFld;
if(!strValue.IsEmpty())
vtFld = strValue;
else
vtFld.vt = VT_NULL;
return PutFieldValue(lpFieldName, vtFld);
I'm having problems creating a tmx map from string input.
bool LevelManager::initLevel(int currentLevel)
{
const char* map;
try {
map = LevelManager::getLevel(currentLevel);
} catch (int) {
throw 1;
}
if(map != NULL){
CCLog("%s", map);
tileMap = CCTMXTiledMap::create(map);
tileMap->setAnchorPoint(ccp(0,0));
tileMap->setPosition(ccp(15,20));
this->addChild(tileMap, 5);
backgoundLayer = tileMap->layerNamed("Background");
} else {
throw 1;
}
return true;
}
Thats my code.
It is very unstable. Most of the times it crashes and sometimes it doesn't.
I'm loading my map from the string map. Wich is a const *char.
My map is named Level1.tmx and when i load the map like this: tileMap = CCTMXTiledMap::create("Level1.tmx"); it always works and never crashes.
And i know for a fact that the value of map is Level1.tmx because i log it in the line before the load.
When it crashes the log outputs this: (lldb)
and on the line tileMap->setAnchorPoint(ccp(0,0)); it says "Thread 1: EXC_BAD_ACCESS (code=2, adress=0x0)
Does anyone know why this happens and how to fix it?
Many thanks.
Ps: i'm using xcode, the latest cocos2d-x release and the iPhone simulator
Edit:
Using breakpoints i checked where things go bad while loading the tilemap.
on the line tileMap = CCTMXTiledMap::create(map);
my variable map is still fine
but on line tileMap->setAnchorPoint(ccp(0,0));
it is suddenly corrupted (most of the time)
It sounds like you're returning a char* string created on the stack, which means the memory may or may not be corrupted, depending on circumstances, moon phases, and what not.
So the question is: How is getLevel defined and what does it do (post the code)?
If you do something like this:
const char* LevelManager::getLevel(int level)
{
char* levelName = "default.tmx";
return levelName;
}
…then that's going to be the culprit. The levelName variable is created on the stack, no memory (on the heap) is allocated for it. The levelName variable and the memory it points to become invalid as soon as the method returns.
Hence when the method leaves this area of memory where levelName points to can be allocated by other parts of the program or other method's stack memory. Whatever is in that area of memory may still be the string, or it may be (partially) overridden by other bits and bytes.
PS: Your exception handling code is …. well it shows a lack of understanding what exception handling does, how to use it and especially when. I hope these are just remnants of trying to get to the bottom of the issue, otherwise get rid of it. I recommend reading a tutorial and introductions on C++ exception handling if you want to continue to use exceptions. Especially something like (map != NULL) should be an assertion, not an exception.
I fixed it.
const char* was to blame.
When returning my map as a char * it worked flawless.
const char *levelFileName = level.attribute("file").value();
char *levelChar = new char[strlen(levelFileName) + 1];
std:: strcpy (levelChar, levelFileName);
return levelChar;
Thats how i now return the map.
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.